diff --git a/.gitignore b/.gitignore index b90aa51640..3ef6b26261 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +config/db.php config/my.php www/data/ www/install.php diff --git a/Makefile b/Makefile index 0d3d8eaa7b..b959bce756 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,8 @@ pms: chmod 777 zentaopms/module chmod 777 zentaopms/www chmod a+rx zentaopms/bin/* + mkdir zentaopms/config/ext + for module in `ls zentaopms/module/`; do mkdir zentaopms/module/$$module/ext; done find zentaopms/ -name ext |xargs chmod -R 777 zip -r -9 ZenTaoPMS.$(VERSION).zip zentaopms rm -fr zentaopms diff --git a/README.md b/README.md index 986ed32761..f855d1538e 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,11 @@ ===================== -ZenTao is an open source project management software, developed by Qingdao Nature Easy Soft Network Technology Co., Ltd. Integrating product management, project management, quality management, document management, organization management and to-do management, ZenTao is a professional development project management tool, covering the core processes of development project management. +ZenTao is an open source project management software, developed by Qingdao Nature Easy Soft Network Technology Co. Ltd. Combining product management, project management, QA management, document management, company management and todo management. It is a professional project management software, covering the core process of software development projects. + + +ZenTao is practical and pragmatic. It has full features and beautiful interfaces, and is easy to use. ZenTao is well structured and can be flexibly extended. It also has powerful search features, various forms of statistical reports and complete API. -ZenTao is practical and pragmatic. It has full features and a beautiful interface, and is easy to operate. Zentao is well structured and can be extended flexibly. It also has powerful search features, various reports and API. ZenTao focuses on development project management! @@ -12,26 +14,26 @@ ZenTao focuses on development project management! ============================ -Zen(禅) and Tao(道) are two Chinese characters that have rich meanings in both religion and culture. ZenTao Project Management Software takes the cutural meaning of Zen and Tao, and is expected to convey our understanding and thinking on management. Inspired by The Tao of Programming and The Zen of Programming, we named our software ZenTao. +Zen(禅) and Tao(道) are the two Chinese characters that have rich meanings in both religion and culture. ZenTao Project Management Software takes the cultural meaning of Zen and Tao, and is expected to convey our understanding and thinking of management. Inspired by The Tao of Programming and The Zen of Programming, we named our software ZenTao. 3. Design philosophy of ZenTao Project Management Software ========================================================== -The main management philosophy of ZenTao Project Management Software is based on Scrum, an internationally popular Agile management methodology. Scrum is very pragmatic and easy to operate, so it fits in the fast iterative software development projects. However, Scrum only defines the core management framework. Therefore, details and workflows have to be extended and developed. Based on the philosophy of Scrum and the observation of the current development situation in China, ZenTao integrates bug management, test management, release management and document management, which covers the entire life cycle of software development. In ZenTao, the concept of product, project and test is clearly defined. Product team, development team and QA team coordinate and check with each other while they function differently. The three teams interact with each other through working on stories, tasks and bugs, and eventually deliver the product with quality. +The main design philosophy of ZenTao Project Management Software is based on Scrum, an internationally popular Agile methodology. Scrum is very pragmatic and easy to operate, so it fits in the fast iterative development of software projects. However, Scrum only defines the core management framework. There are still many details and processes that have to be extended and developed. Based on the philosophy of Scrum and with the observation of the current development situations in China, ZenTao integrates bug management, test case management, release management and document management, and it completely covers the entire lifecycle of software development. In ZenTao, the concepts of product, project and test are clearly defined. Product team, development team and QA team coordinate and check with each other while they function differently. The three teams interact with each other through stories, tasks and bugs, and eventually deliver the product with quality. 4. Why choose ZenTao Project Management Software? =============================================== -* ZenTao is a professional development project management software and canot be replaced by one simple project management software. +* ZenTao is a professional development project management software and cannot be replaced by any simple project management software. * ZenTao has precise and pragmatic management philosphy, which will accelerate Agile development. * ZenTao has full features as a project management software, so you don’t have to integrate several systems together, like mantisbt + trac + testlink. * Open source codes and flexible extension mechanism. It is convenient to use and develop based on ZenTao. -* Underlying framework and front-end UI framework developed independently; robust and stable with beautiful interface and friendly interaction. +* Underlying framework and frontend UI framework are developed independently; robust and stable with beautiful interface and friendly interaction. * Perfect community mechanism; you can get technical support and help in time. -* Zero input, which means you have no risk for choosing ZenTao compared with other commercial software that cost you thousands of dollars. -* Support various ways of deployment, either private deployment or cloud service. +* Zero input, which means you have no risk for choosing ZenTao, compared with other commercial software that cost you thousands of dollars. +* Support various deployments, either private or cloud. 5. Features of ZenTao Project Management Software @@ -39,15 +41,15 @@ The main management philosophy of ZenTao Project Management Software is based on ====================================================== * Product management: including products, stories, plans, releases and roadmaps; -* Project management: including projects, tasks, teams, versions and burn-down charts; +* Project management: including projects, tasks, teams, builds and burn-down charts; * Quality management: including bugs, test cases, test tasks and test results; * Document management: including product document library, project document library and customized document library; * Work management: including to-do management and personal management, such as my tasks, my bugs, my story and my projects; * Organization management: including department, users, groups and privileges; * Statistics: various reports; -* Search: powerful search features to help you find the data you need. -* Extension mechanism: extensible almost anywhere in ZenTao; -* API mechanism, visible API: convenient for integration with other systems. +* Search: powerful search functions to help you find the data you need. +* Extension mechanism: extensible in almost any parts of ZenTao; +* API mechanism: convenient for integration with other systems. 6. Website diff --git a/VERSION b/VERSION index d1c0682f9d..072e6075b0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.6.3 +10.0.beta diff --git a/config/config.php b/config/config.php index b01c02e9c7..29b8779a8b 100644 --- a/config/config.php +++ b/config/config.php @@ -5,7 +5,7 @@ * * The author disclaims copyright to this source code. In place of * a legal notice, here is a blessing: - * + * * May you do good and not evil. * May you find forgiveness for yourself and forgive others. * May you share freely, never taking more than you give. @@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}} if(!function_exists('getWebRoot')){function getWebRoot(){}} /* 基本设置。Basic settings. */ -$config->version = '9.6.3'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it. +$config->version = '10.0.beta'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it. $config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP. $config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time. $config->timezone = 'Asia/Shanghai'; // 时区设置。 The time zone setting, for more see http://www.php.net/manual/en/timezones.php. @@ -32,12 +32,12 @@ $config->sessionVar = 'zentaosid'; // 请求类型为GET:session变 $config->views = ',html,json,mhtml,'; // 支持的视图类型。 Supported view formats. /* 支持的主题和语言。Supported thems and languages. */ -$config->themes['default'] = 'default'; +$config->themes['default'] = 'default'; $config->langs['zh-cn'] = '简体'; $config->langs['zh-tw'] = '繁體'; $config->langs['en'] = 'English'; -/* 设备类型视图文件前缀。The prefix for view file for different device. */ +/* 设备类型视图文件前缀。The prefix for view file for different device. */ $config->devicePrefix['mhtml'] = ''; /* 默认值设置。Default settings. */ @@ -80,7 +80,7 @@ $config->domainPostfix .= "|rocks|social|co.com|bio|reviews|link|sexy|us.com|con $config->domainPostfix .= "|menu|info|events|webcam|dating|vacations|flights|cruises|global|ca|guru|"; $config->domainPostfix .= "|futbol|rentals|dance|lawyer|attorney|democrat|republican|actor|condos|immobilien|"; $config->domainPostfix .= "|villas|foundation|expert|works|tools|watch|zone|bargains|agency|best|solar|"; -$config->domainPostfix .= "|farm|pics|photo|marketing|holiday|gift|buzz|guitars|trade|construction|"; +$config->domainPostfix .= "|farm|pics|photo|marketing|holiday|gift|buzz|guitars|trade|construction|"; $config->domainPostfix .= "|international|house|coffee|florist|rich|ceo|camp|education|repair|win|site|"; /* 系统框架配置。Framework settings. */ @@ -103,7 +103,7 @@ $config->framework->detectDevice['zh-tw'] = true; // 在zh-tw语言情况下, $config->framework->detectDevice['en'] = true; // 在en语言情况下,是否启用设备检测功能。 Whether enable device detect or not. /* 文件上传设置。 Upload settings. */ -$config->file = new stdclass(); +$config->file = new stdclass(); $config->file->dangers = 'php,php3,php4,phtml,php5,jsp,py,rb,asp,aspx,ashx,asa,cer,cdx,aspl,shtm,shtml,html,htm'; $config->file->allowed = 'txt,doc,docx,dot,wps,wri,pdf,ppt,pptx,xls,xlsx,ett,xlt,xlsm,csv,jpg,jpeg,png,psd,gif,ico,bmp,swf,avi,rmvb,rm,mp3,mp4,3gp,flv,mov,movie,rar,zip,bz,bz2,tar,gz,mpp,rp,pdm,vsdx,vsd,sql'; @@ -111,6 +111,14 @@ $config->file->allowed = 'txt,doc,docx,dot,wps,wri,pdf,ppt,pptx,xls,xlsx,ett,xlt $filterConfig = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'filter.php'; if(file_exists($filterConfig)) include $filterConfig; +/* 引用数据库的配置。 Include the database config file. */ +$dbConfig = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'db.php'; +if(file_exists($dbConfig)) include $dbConfig; + +/* 引用自定义的配置。 Include the custom config file. */ +$myConfig = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'my.php'; +if(file_exists($myConfig)) include $myConfig; + /* 禅道配置文件。zentaopms settings. */ $zentaopmsConfig = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'zentaopms.php'; if(file_exists($zentaopmsConfig)) include $zentaopmsConfig; @@ -118,7 +126,3 @@ if(file_exists($zentaopmsConfig)) include $zentaopmsConfig; /* Include extension config files. */ $extConfigFiles = glob(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'ext/*.php'); if($extConfigFiles) foreach($extConfigFiles as $extConfigFile) include $extConfigFile; - -/* 引用自定义的配置。 Include the custom config file. */ -$myConfig = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'my.php'; -if(file_exists($myConfig)) include $myConfig; diff --git a/config/filter.php b/config/filter.php index 66e2c6ce16..6b684691fd 100644 --- a/config/filter.php +++ b/config/filter.php @@ -53,6 +53,7 @@ $filter->bug->default = new stdclass(); $filter->bug->create = new stdclass(); $filter->bug->export = new stdclass(); $filter->doc->browse = new stdclass(); +$filter->doc->showfiles = new stdclass(); $filter->doc->default = new stdclass(); $filter->doc->showfiles = new stdclass(); $filter->mail->ztcloud = new stdclass(); @@ -99,6 +100,7 @@ $filter->bug->export->cookie['checkedItem'] = 'reg::checked'; $filter->doc->browse->cookie['browseType'] = 'reg::browseType'; $filter->doc->default->cookie['from'] = 'code'; $filter->doc->default->cookie['product'] = 'int'; +$filter->doc->showfiles->cookie['docFilesViewType'] = 'code'; $filter->file->download->cookie[$config->sessionVar] = 'code'; @@ -203,4 +205,4 @@ $filter->user->edit->get['from'] = 'reg::word'; $filter->git->cat->get['repoUrl'] = 'reg::base64'; $filter->git->diff->get['repoUrl'] = 'reg::base64'; $filter->svn->cat->get['repoUrl'] = 'reg::base64'; -$filter->svn->diff->get['repoUrl'] = 'reg::base64'; \ No newline at end of file +$filter->svn->diff->get['repoUrl'] = 'reg::base64'; diff --git a/config/zentaopms.php b/config/zentaopms.php index a7149c59c1..949a5a8146 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -95,7 +95,6 @@ define('TABLE_FILE', '`' . $config->db->prefix . 'file`'); define('TABLE_HISTORY', '`' . $config->db->prefix . 'history`'); define('TABLE_EXTENSION', '`' . $config->db->prefix . 'extension`'); define('TABLE_CRON', '`' . $config->db->prefix . 'cron`'); -define('TABLE_MAILQUEUE', '`' . $config->db->prefix . 'mailqueue`'); define('TABLE_BLOCK', '`' . $config->db->prefix . 'block`'); define('TABLE_DOCCONTENT', '`' . $config->db->prefix . 'doccontent`'); define('TABLE_TESTSUITE', '`' . $config->db->prefix . 'testsuite`'); @@ -104,9 +103,9 @@ define('TABLE_TESTREPORT', '`' . $config->db->prefix . 'testreport`'); define('TABLE_ENTRY', '`' . $config->db->prefix . 'entry`'); define('TABLE_WEBHOOK', '`' . $config->db->prefix . 'webhook`'); -define('TABLE_WEBHOOKDATAS', '`' . $config->db->prefix . 'webhookdatas`'); define('TABLE_LOG', '`' . $config->db->prefix . 'log`'); define('TABLE_SCORE', '`' . $config->db->prefix . 'score`'); +define('TABLE_NOTIFY', '`' . $config->db->prefix . 'notify`'); if(!defined('TABLE_LANG')) define('TABLE_LANG', '`' . $config->db->prefix . 'lang`'); $config->objectTables['product'] = TABLE_PRODUCT; diff --git a/db/demo.sql b/db/demo.sql index c1979dd99c..cd67150a07 100644 --- a/db/demo.sql +++ b/db/demo.sql @@ -267,21 +267,21 @@ INSERT INTO `zt_task` (`id`, `project`, `story`, `storyVersion`, `fromBug`, `nam INSERT INTO `zt_task` (`id`, `project`, `story`, `storyVersion`, `fromBug`, `name`, `type`, `pri`, `estimate`, `consumed`, `left`, `deadline`, `status`, `mailto`, `desc`, `openedBy`, `openedDate`, `assignedTo`, `assignedDate`, `finishedBy`, `finishedDate`, `canceledBy`, `canceledDate`, `closedBy`, `closedDate`, `closedReason`, `lastEditedBy`, `lastEditedDate`, `deleted`) VALUES(8, 1, 4, 1, 0, '售后服务的开发', 'devel', 1, 8, 6, 0, '0000-00-00', 'cancel', '', '售后服务的开发
', 'projectManager', '2012-06-05 10:34:45', 'projectManager', '2012-06-05 10:41:20', 'dev1', '0000-00-00 00:00:00', 'dev1', '2012-06-05 10:41:20', '', '0000-00-00 00:00:00', '', 'dev1', '2012-06-05 10:41:20', '0'); INSERT INTO `zt_task` (`id`, `project`, `story`, `storyVersion`, `fromBug`, `name`, `type`, `pri`, `estimate`, `consumed`, `left`, `deadline`, `status`, `mailto`, `desc`, `openedBy`, `openedDate`, `assignedTo`, `assignedDate`, `finishedBy`, `finishedDate`, `canceledBy`, `canceledDate`, `closedBy`, `closedDate`, `closedReason`, `lastEditedBy`, `lastEditedDate`, `deleted`) VALUES(9, 1, 4, 1, 0, '售后服务的开发', 'devel', 1, 8, 0, 8, '0000-00-00', 'cancel', '', '售后服务的开发
', 'projectManager', '2012-06-05 10:35:01', 'projectManager', '2012-06-05 10:41:20', '', '0000-00-00 00:00:00', 'dev1', '2012-06-05 10:41:20', '', '0000-00-00 00:00:00', '', 'dev1', '2012-06-05 10:41:20', '0'); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'dev3', '研发', '2013-02-20', 184, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'productManager', '产品经理', '2013-02-20', 184, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'tester2', '测试', '2013-02-20', 184, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'tester1', '测试', '2013-02-20', 184, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'projectManager', '项目经理', '2013-02-20', 365, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'tester2', '测试', '2013-02-20', 365, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'tester1', '测试', '2013-02-20', 365, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'dev3', '研发', '2013-02-20', 365, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'dev2', '研发', '2013-02-20', 365, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'dev1', '研发', '2013-02-20', 365, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'dev1', '研发', '2013-02-20', 184, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'dev2', '研发', '2013-02-20', 184, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'projectManager', '项目经理', '2013-02-20', 184, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'testManager', '测试主管', '2013-02-20', 184, 7); -INSERT INTO `zt_team` (`project`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'productManager', '产品经理', '2013-02-20', 365, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'project', 'dev3', '研发', '2013-02-20', 184, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'project', 'productManager', '产品经理', '2013-02-20', 184, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'project', 'tester2', '测试', '2013-02-20', 184, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'project', 'tester1', '测试', '2013-02-20', 184, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'project', 'projectManager', '项目经理', '2013-02-20', 365, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'project', 'tester2', '测试', '2013-02-20', 365, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'project', 'tester1', '测试', '2013-02-20', 365, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'project', 'dev3', '研发', '2013-02-20', 365, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'project', 'dev2', '研发', '2013-02-20', 365, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'project', 'dev1', '研发', '2013-02-20', 365, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'project', 'dev1', '研发', '2013-02-20', 184, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'project', 'dev2', '研发', '2013-02-20', 184, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'project', 'projectManager', '项目经理', '2013-02-20', 184, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(1, 'project', 'testManager', '测试主管', '2013-02-20', 184, 7); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `join`, `days`, `hours`) VALUES(2, 'project', 'productManager', '产品经理', '2013-02-20', 365, 7); INSERT INTO `zt_testresult` (`id`, `run`, `case`, `version`, `caseResult`, `stepResults`, `lastRunner`, `date`) VALUES(1, 4, 1, 1, 'pass', 'a:1:{i:1;a:2:{s:6:"result";s:4:"pass";s:4:"real";s:0:"";}}', 'testManager', '2012-06-05 11:11:00'); INSERT INTO `zt_testresult` (`id`, `run`, `case`, `version`, `caseResult`, `stepResults`, `lastRunner`, `date`) VALUES(2, 3, 2, 1, 'pass', 'a:1:{i:2;a:2:{s:6:"result";s:4:"pass";s:4:"real";s:0:"";}}', 'testManager', '2012-06-05 11:11:05'); @@ -295,16 +295,15 @@ INSERT INTO `zt_testrun` (`id`, `task`, `case`, `version`, `assignedTo`, `lastRu INSERT INTO `zt_testtask` (`id`, `name`, `product`, `project`, `build`, `owner`, `begin`, `end`, `desc`, `status`, `deleted`) VALUES(1, '企业网站第一期测试任务', 1, 1, 'trunk', 'testManager', '2012-06-05', '2013-06-21', '', 'wait', '0'); - INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(2, 5, 'productManager', 'e10adc3949ba59abbe56e057f20f883e', 'po', '产品经理', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 3, '192.168.0.8', 1338866083, '0'); INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(3, 6, 'projectManager', 'e10adc3949ba59abbe56e057f20f883e', 'pm', '项目经理', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 3, '192.168.0.8', 1338865876, '0'); -INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(4, 2, 'dev1', 'e10adc3949ba59abbe56e057f20f883e', 'dev', '开发甲', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 1, '192.168.0.8', 1338863860, '0'); -INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(5, 2, 'dev2', 'e10adc3949ba59abbe56e057f20f883e', 'dev', '开发乙', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 1, '192.168.0.8', 1338864116, '0'); -INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(6, 2, 'dev3', 'e10adc3949ba59abbe56e057f20f883e', 'dev', '开发丙', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 1, '192.168.0.8', 1338864187, '0'); -INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(7, 3, 'tester1', 'e10adc3949ba59abbe56e057f20f883e', 'qa', '测试甲', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 3, '192.168.0.8', 1338865739, '0'); -INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(8, 3, 'tester2', 'e10adc3949ba59abbe56e057f20f883e', 'qa', '测试乙', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 2, '192.168.0.8', 1338865450, '0'); -INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(9, 3, 'tester3', 'e10adc3949ba59abbe56e057f20f883e', 'qa', '测试丙', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 1, '192.168.0.8', 1338865125, '0'); -INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(10, 1, 'testManager', 'e10adc3949ba59abbe56e057f20f883e', 'qd', '测试经理', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 6, '192.168.0.8', 1338865842, '0'); +INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(4, 2, 'dev1', 'e10adc3949ba59abbe56e057f20f883e', 'dev', '开发甲', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 1, '192.168.0.8', 1338863860, '1'); +INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(5, 2, 'dev2', 'e10adc3949ba59abbe56e057f20f883e', 'dev', '开发乙', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 1, '192.168.0.8', 1338864116, '1'); +INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(6, 2, 'dev3', 'e10adc3949ba59abbe56e057f20f883e', 'dev', '开发丙', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 1, '192.168.0.8', 1338864187, '1'); +INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(7, 3, 'tester1', 'e10adc3949ba59abbe56e057f20f883e', 'qa', '测试甲', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 3, '192.168.0.8', 1338865739, '1'); +INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(8, 3, 'tester2', 'e10adc3949ba59abbe56e057f20f883e', 'qa', '测试乙', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 2, '192.168.0.8', 1338865450, '1'); +INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(9, 3, 'tester3', 'e10adc3949ba59abbe56e057f20f883e', 'qa', '测试丙', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 1, '192.168.0.8', 1338865125, '1'); +INSERT INTO `zt_user` (`id`, `dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `deleted`) VALUES(10, 1, 'testManager', 'e10adc3949ba59abbe56e057f20f883e', 'qd', '测试经理', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 6, '192.168.0.8', 1338865842, '1'); INSERT INTO `zt_usergroup` (`account`, `group`) VALUES('productManager', 5); INSERT INTO `zt_usergroup` (`account`, `group`) VALUES('projectManager', 4); diff --git a/db/endemo.sql b/db/endemo.sql index 236a16b9a6..536c07c535 100644 --- a/db/endemo.sql +++ b/db/endemo.sql @@ -39,15 +39,15 @@ INSERT INTO `zt_action` (`id`, `objectType`, `objectID`, `product`, `project`, ` (33, 'user', 1, ',0,', 0, 'admin', 'login', '2017-12-12 15:18:58', '', '', '0'), (34, 'user', 10, ',0,', 0, 'admin', 'deleted', '2017-12-12 15:20:05', '', '1', '0'), (35, 'user', 1, ',0,', 0, 'admin', 'logout', '2017-12-12 15:22:11', '', '', '0'), -(36, 'user', 12, ',0,', 0, 'theQS', 'login', '2017-12-12 15:22:36', '', '', '0'), -(37, 'user', 12, ',0,', 0, 'theQS', 'logout', '2017-12-12 15:22:48', '', '', '0'), +(36, 'user', 12, ',0,', 0, 'pm1', 'login', '2017-12-12 15:22:36', '', '', '0'), +(37, 'user', 12, ',0,', 0, 'pm1', 'logout', '2017-12-12 15:22:48', '', '', '0'), (38, 'user', 1, ',0,', 0, 'admin', 'login', '2017-12-12 15:23:02', '', '', '0'), (39, 'user', 1, ',0,', 0, 'admin', 'logout', '2017-12-12 15:23:27', '', '', '0'), -(40, 'user', 11, ',0,', 0, 'qa1', 'login', '2017-12-12 15:23:34', '', '', '0'), -(41, 'build', 1, ',1,', 1, 'qa1', 'opened', '2017-12-12 15:25:13', '', '', '0'), -(42, 'bug', 1, ',1,', 1, 'qa1', 'opened', '2017-12-12 15:27:56', '', '', '0'), -(43, 'bug', 2, ',1,', 1, 'qa1', 'opened', '2017-12-12 15:30:32', '', '', '0'), -(44, 'user', 11, ',0,', 0, 'qa1', 'logout', '2017-12-12 15:32:26', '', '', '0'), +(40, 'user', 11, ',0,', 0, 'pm1', 'login', '2017-12-12 15:23:34', '', '', '0'), +(41, 'build', 1, ',1,', 1, 'pm1', 'opened', '2017-12-12 15:25:13', '', '', '0'), +(42, 'bug', 1, ',1,', 1, 'pm1', 'opened', '2017-12-12 15:27:56', '', '', '0'), +(43, 'bug', 2, ',1,', 1, 'pm1', 'opened', '2017-12-12 15:30:32', '', '', '0'), +(44, 'user', 11, ',0,', 0, 'pm1', 'logout', '2017-12-12 15:32:26', '', '', '0'), (45, 'user', 1, ',0,', 0, 'admin', 'login', '2017-12-12 15:32:41', '', '', '0'), (46, 'project', 1, ',1,', 1, 'admin', 'started', '2017-12-12 15:32:54', '', '', '0'), (47, 'product', 2, ',2,', 0, 'admin', 'opened', '2017-12-12 23:28:29', '', '', '0'), @@ -80,54 +80,54 @@ INSERT INTO `zt_action` (`id`, `objectType`, `objectID`, `product`, `project`, ` (74, 'task', 8, ',2,', 2, 'pm1', 'started', '2017-12-12 23:45:36', '', '', '0'), (75, 'task', 7, ',2,', 2, 'pm1', 'recordestimate', '2017-12-12 23:45:53', '', '8', '0'), (76, 'user', 3, ',0,', 0, 'pm1', 'logout', '2017-12-12 23:46:28', '', '', '0'), -(77, 'user', 5, ',0,', 0, 'pg1', 'login', '2017-12-12 23:46:35', '', '', '0'), -(78, 'task', 9, ',2,', 2, 'pg1', 'started', '2017-12-12 23:46:58', '', '', '0'), -(79, 'task', 5, ',2,', 2, 'pg1', 'started', '2017-12-12 23:47:03', '', '', '0'), -(80, 'task', 5, ',2,', 2, 'pg1', 'finished', '2017-12-12 23:47:37', 'Finished general setup at backend', '', '0'), -(81, 'user', 5, ',0,', 0, 'pg1', 'logout', '2017-12-12 23:48:31', '', '', '0'), -(82, 'user', 7, ',0,', 0, 'pg3', 'login', '2017-12-12 23:48:39', '', '', '0'), -(83, 'build', 2, ',2,', 2, 'pg3', 'opened', '2017-12-12 23:49:31', '', '', '0'), -(84, 'task', 9, ',2,', 2, 'pg3', 'recordestimate', '2017-12-12 23:51:14', 'Finished page design.', '8', '0'), -(85, 'user', 7, ',0,', 0, 'pg3', 'logout', '2017-12-12 23:52:27', '', '', '0'), +(77, 'user', 5, ',0,', 0, 'pm1', 'login', '2017-12-12 23:46:35', '', '', '0'), +(78, 'task', 9, ',2,', 2, 'pm1', 'started', '2017-12-12 23:46:58', '', '', '0'), +(79, 'task', 5, ',2,', 2, 'pm1', 'started', '2017-12-12 23:47:03', '', '', '0'), +(80, 'task', 5, ',2,', 2, 'pm1', 'finished', '2017-12-12 23:47:37', 'Finished general setup at backend', '', '0'), +(81, 'user', 5, ',0,', 0, 'pm1', 'logout', '2017-12-12 23:48:31', '', '', '0'), +(82, 'user', 7, ',0,', 0, 'pm1', 'login', '2017-12-12 23:48:39', '', '', '0'), +(83, 'build', 2, ',2,', 2, 'pm1', 'opened', '2017-12-12 23:49:31', '', '', '0'), +(84, 'task', 9, ',2,', 2, 'pm1', 'recordestimate', '2017-12-12 23:51:14', 'Finished page design.', '8', '0'), +(85, 'user', 7, ',0,', 0, 'pm1', 'logout', '2017-12-12 23:52:27', '', '', '0'), (86, 'user', 2, ',0,', 0, 'thePO', 'login', '2017-12-12 23:52:30', '', '', '0'), (87, 'story', 10, ',2,', 2, 'thePO', 'edited', '2017-12-12 23:52:40', '', '', '0'), (88, 'story', 11, ',2,', 2, 'thePO', 'edited', '2017-12-12 23:53:04', '', '', '0'), (89, 'project', 2, ',2,', 2, 'thePO', 'started', '2017-12-12 23:54:13', '', '', '0'), (90, 'user', 2, ',0,', 0, 'thePO', 'logout', '2017-12-12 23:55:42', '', '', '0'), -(91, 'user', 7, ',0,', 0, 'pg3', 'login', '2017-12-12 23:55:49', '', '', '0'), -(92, 'testtask', 1, ',2,', 2, 'pg3', 'opened', '2017-12-12 23:56:59', '', '', '0'), -(93, 'user', 7, ',0,', 0, 'pg3', 'logout', '2017-12-12 23:57:22', '', '', '0'), -(94, 'user', 11, ',0,', 0, 'qa1', 'login', '2017-12-12 23:57:33', '', '', '0'), -(95, 'case', 1, ',2,', 0, 'qa1', 'opened', '2017-12-13 00:00:29', '', '', '0'), -(96, 'case', 2, ',2,', 0, 'qa1', 'opened', '2017-12-13 00:04:09', '', '', '0'), -(97, 'testsuite', 1, ',0,', 0, 'qa1', 'opened', '2017-12-13 00:05:13', '', '', '0'), -(98, 'bug', 3, ',2,', 2, 'qa1', 'opened', '2017-12-13 00:09:48', '', '', '0'), -(99, 'case', 3, ',2,', 0, 'qa1', 'opened', '2017-12-13 00:13:25', '', '', '0'), -(100, 'case', 2, ',2,', 0, 'qa1', 'edited', '2017-12-13 00:18:17', '', '', '0'), -(101, 'bug', 4, ',2,', 2, 'qa1', 'opened', '2017-12-13 00:30:07', '', '', '0'), -(102, 'bug', 4, ',2,', 2, 'qa1', 'edited', '2017-12-13 00:30:41', '', '', '0'), -(103, 'bug', 3, ',2,', 2, 'qa1', 'edited', '2017-12-13 00:31:10', '', '', '0'), -(104, 'bug', 5, ',2,', 2, 'qa1', 'opened', '2017-12-13 00:32:08', '', '', '0'), -(105, 'user', 11, ',0,', 0, 'qa1', 'logout', '2017-12-13 00:34:34', '', '', '0'); +(91, 'user', 7, ',0,', 0, 'pm1', 'login', '2017-12-12 23:55:49', '', '', '0'), +(92, 'testtask', 1, ',2,', 2, 'pm1', 'opened', '2017-12-12 23:56:59', '', '', '0'), +(93, 'user', 7, ',0,', 0, 'pm1', 'logout', '2017-12-12 23:57:22', '', '', '0'), +(94, 'user', 11, ',0,', 0, 'pm1', 'login', '2017-12-12 23:57:33', '', '', '0'), +(95, 'case', 1, ',2,', 0, 'pm1', 'opened', '2017-12-13 00:00:29', '', '', '0'), +(96, 'case', 2, ',2,', 0, 'pm1', 'opened', '2017-12-13 00:04:09', '', '', '0'), +(97, 'testsuite', 1, ',0,', 0, 'pm1', 'opened', '2017-12-13 00:05:13', '', '', '0'), +(98, 'bug', 3, ',2,', 2, 'pm1', 'opened', '2017-12-13 00:09:48', '', '', '0'), +(99, 'case', 3, ',2,', 0, 'pm1', 'opened', '2017-12-13 00:13:25', '', '', '0'), +(100, 'case', 2, ',2,', 0, 'pm1', 'edited', '2017-12-13 00:18:17', '', '', '0'), +(101, 'bug', 4, ',2,', 2, 'pm1', 'opened', '2017-12-13 00:30:07', '', '', '0'), +(102, 'bug', 4, ',2,', 2, 'pm1', 'edited', '2017-12-13 00:30:41', '', '', '0'), +(103, 'bug', 3, ',2,', 2, 'pm1', 'edited', '2017-12-13 00:31:10', '', '', '0'), +(104, 'bug', 5, ',2,', 2, 'pm1', 'opened', '2017-12-13 00:32:08', '', '', '0'), +(105, 'user', 11, ',0,', 0, 'pm1', 'logout', '2017-12-13 00:34:34', '', '', '0'); INSERT INTO `zt_bug` (`id`, `product`, `branch`, `module`, `project`, `plan`, `story`, `storyVersion`, `task`, `toTask`, `toStory`, `title`, `keywords`, `severity`, `pri`, `type`, `os`, `browser`, `hardware`, `found`, `steps`, `status`, `color`, `confirmed`, `activatedCount`, `activatedDate`, `mailto`, `openedBy`, `openedDate`, `openedBuild`, `assignedTo`, `assignedDate`, `deadline`, `resolvedBy`, `resolution`, `resolvedBuild`, `resolvedDate`, `closedBy`, `closedDate`, `duplicateBug`, `linkBug`, `case`, `caseVersion`, `result`, `testtask`, `lastEditedBy`, `lastEditedDate`, `deleted`) VALUES -(1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 'Switch desktops three time, then the order of desktops is different from that before.', '', 3, 0, 'codeerror', 'all', '', '', '', '

[Steps]Switch desktops three times.

\r\n

[Results]The order of desktops is different from that was before.

\r\n

[Expectations]The order of desktops is the same as that was before.

', 'active', '', 0, 0, '0000-00-00 00:00:00', ',pm1', 'qa1', '2017-12-12 15:27:55', '1', 'pm1', '2017-12-12 15:27:55', '2017-12-16', '', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 0, '', 0, 0, 0, 0, '', '0000-00-00 00:00:00', '0'), -(2, 1, 0, 2, 1, 0, 0, 1, 0, 0, 0, 'Full text retrieval in Word files. If Chinese characters exist in the file, it cannot be retrieved.', '', 3, 0, 'codeerror', '', '', '', '', '

[Steps]Enter “禅道(ZenTao)” in a Word and serach “禅道”.

\r\n

[Results] “禅道” is not found.

\r\n

[Expectations] “禅道” is found.

', 'active', '', 0, 0, '0000-00-00 00:00:00', '', 'qa1', '2017-12-12 15:30:32', '1', 'pm1', '2017-12-12 15:30:32', '0000-00-00', '', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 0, '', 0, 0, 0, 0, '', '0000-00-00 00:00:00', '0'), -(3, 2, 0, 8, 2, 0, 10, 1, 0, 0, 0, '400 page is incomplete.', '', 3, 0, 'codeerror', '', '', '', '', '

[Steps]

\r\n1. Click “400 page”

[Results]

\r\n1. Not all 400 page is displayed.

[Expectations]

\r\n1. List all 400 error pages.
', 'active', '', 0, 0, '0000-00-00 00:00:00', '', 'qa1', '2017-12-13 00:09:48', '2', '', '0000-00-00 00:00:00', '0000-00-00', '', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 0, '', 2, 1, 1, 1, 'qa1', '2017-12-13 00:31:10', '0'), -(4, 2, 0, 8, 2, 0, 10, 1, 0, 0, 0, 'Generate sitemap.', '', 3, 0, 'codeerror', '', '', '', '', '

[Steps]

\r\n1. Click “Generate sitemap”.

[Results]

\r\n1. ‘Contact Us’ page is missing in sitemap.

[Expectations]

\r\n1. Generate sitemap.
', 'active', '', 0, 0, '0000-00-00 00:00:00', '', 'qa1', '2017-12-13 00:30:07', '2', '', '0000-00-00 00:00:00', '0000-00-00', '', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 0, '', 2, 2, 0, 0, 'qa1', '2017-12-13 00:30:41', '0'), -(5, 2, 0, 8, 2, 0, 10, 1, 0, 0, 0, 'Database error in adding blogroll.', '', 3, 0, 'codeerror', '', '', '', '', '

[Steps]

\r\n1. Add ”www.zentao.pm\"

[Results]

\r\n1. It cannot be added, and database error prompts.

[Expectations]

1. In database form ‘friend link’, add ”www.zentao.pm\"
', 'active', '', 0, 0, '0000-00-00 00:00:00', '', 'qa1', '2017-12-13 00:32:08', '2', '', '0000-00-00 00:00:00', '0000-00-00', '', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 0, '', 2, 2, 0, 0, '', '0000-00-00 00:00:00', '0'); +(1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 'Switch desktops three time, then the order of desktops is different from that before.', '', 3, 0, 'codeerror', 'all', '', '', '', '

[Steps]Switch desktops three times.

\r\n

[Results]The order of desktops is different from that was before.

\r\n

[Expectations]The order of desktops is the same as that was before.

', 'active', '', 0, 0, '0000-00-00 00:00:00', ',pm1', 'pm1', '2017-12-12 15:27:55', '1', 'pm1', '2017-12-12 15:27:55', '2017-12-16', '', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 0, '', 0, 0, 0, 0, '', '0000-00-00 00:00:00', '0'), +(2, 1, 0, 2, 1, 0, 0, 1, 0, 0, 0, 'Full text retrieval in Word files. If Chinese characters exist in the file, it cannot be retrieved.', '', 3, 0, 'codeerror', '', '', '', '', '

[Steps]Enter “禅道(ZenTao)” in a Word and serach “禅道”.

\r\n

[Results] “禅道” is not found.

\r\n

[Expectations] “禅道” is found.

', 'active', '', 0, 0, '0000-00-00 00:00:00', '', 'pm1', '2017-12-12 15:30:32', '1', 'pm1', '2017-12-12 15:30:32', '0000-00-00', '', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 0, '', 0, 0, 0, 0, '', '0000-00-00 00:00:00', '0'), +(3, 2, 0, 8, 2, 0, 10, 1, 0, 0, 0, '400 page is incomplete.', '', 3, 0, 'codeerror', '', '', '', '', '

[Steps]

\r\n1. Click “400 page”

[Results]

\r\n1. Not all 400 page is displayed.

[Expectations]

\r\n1. List all 400 error pages.
', 'active', '', 0, 0, '0000-00-00 00:00:00', '', 'pm1', '2017-12-13 00:09:48', '2', '', '0000-00-00 00:00:00', '0000-00-00', '', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 0, '', 2, 1, 1, 1, 'pm1', '2017-12-13 00:31:10', '0'), +(4, 2, 0, 8, 2, 0, 10, 1, 0, 0, 0, 'Generate sitemap.', '', 3, 0, 'codeerror', '', '', '', '', '

[Steps]

\r\n1. Click “Generate sitemap”.

[Results]

\r\n1. ‘Contact Us’ page is missing in sitemap.

[Expectations]

\r\n1. Generate sitemap.
', 'active', '', 0, 0, '0000-00-00 00:00:00', '', 'pm1', '2017-12-13 00:30:07', '2', '', '0000-00-00 00:00:00', '0000-00-00', '', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 0, '', 2, 2, 0, 0, 'pm1', '2017-12-13 00:30:41', '0'), +(5, 2, 0, 8, 2, 0, 10, 1, 0, 0, 0, 'Database error in adding blogroll.', '', 3, 0, 'codeerror', '', '', '', '', '

[Steps]

\r\n1. Add ”www.zentao.pm\"

[Results]

\r\n1. It cannot be added, and database error prompts.

[Expectations]

1. In database form ‘friend link’, add ”www.zentao.pm\"
', 'active', '', 0, 0, '0000-00-00 00:00:00', '', 'pm1', '2017-12-13 00:32:08', '2', '', '0000-00-00 00:00:00', '0000-00-00', '', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 0, '', 2, 2, 0, 0, '', '0000-00-00 00:00:00', '0'); INSERT INTO `zt_build` (`id`, `product`, `branch`, `project`, `name`, `scmPath`, `filePath`, `date`, `stories`, `bugs`, `builder`, `desc`, `deleted`) VALUES -(1, 1, 0, 1, 'win10 V1.0build1', '', '', '2017-12-12', '', '', 'qa1', '', '0'), -(2, 2, 0, 2, 'blog v0.1', '', '', '2017-12-12', '', '', 'pg3', 'build for inner test
', '0'); +(1, 1, 0, 1, 'win10 V1.0build1', '', '', '2017-12-12', '', '', 'pm1', '', '0'), +(2, 2, 0, 2, 'blog v0.1', '', '', '2017-12-12', '', '', 'pm1', 'build for inner test
', '0'); INSERT INTO `zt_burn` (`project`, `date`, `estimate`, `left`, `consumed`) VALUES (1, '2017-12-12', 280, 184, 68); INSERT INTO `zt_case` (`id`, `product`, `branch`, `lib`, `module`, `path`, `story`, `storyVersion`, `title`, `precondition`, `keywords`, `pri`, `type`, `stage`, `howRun`, `scriptedBy`, `scriptedDate`, `scriptStatus`, `scriptLocation`, `status`, `color`, `frequency`, `order`, `openedBy`, `openedDate`, `reviewedBy`, `reviewedDate`, `lastEditedBy`, `lastEditedDate`, `version`, `linkCase`, `fromBug`, `fromCaseID`, `deleted`, `lastRunner`, `lastRunDate`, `lastRunResult`) VALUES -(1, 2, 0, 0, 8, 0, 11, 1, 'Cache setup test', '', '', 3, 'feature', ',unittest,feature', '', '', '0000-00-00', '', '', 'normal', '', '1', 0, 'qa1', '2017-12-13 00:00:29', '', '0000-00-00', '', '0000-00-00 00:00:00', 1, '', 0, 0, '0', 'qa1', '2017-12-13 00:10:24', 'pass'), -(2, 2, 0, 0, 8, 0, 10, 1, 'SEO setup test', '', '', 2, 'feature', ',feature', '', '', '0000-00-00', '', '', 'normal', '', '1', 0, 'qa1', '2017-12-13 00:04:09', '', '0000-00-00', 'qa1', '2017-12-13 00:18:17', 2, '', 0, 0, '0', 'qa1', '2017-12-13 00:23:48', 'fail'), -(3, 2, 0, 0, 8, 0, 0, 1, 'general setup test', '', '', 3, 'feature', '', '', '', '0000-00-00', '', '', 'normal', '', '1', 0, 'qa1', '2017-12-13 00:13:25', '', '0000-00-00', '', '0000-00-00 00:00:00', 1, '', 0, 0, '0', '', '0000-00-00 00:00:00', ''); +(1, 2, 0, 0, 8, 0, 11, 1, 'Cache setup test', '', '', 3, 'feature', ',unittest,feature', '', '', '0000-00-00', '', '', 'normal', '', '1', 0, 'pm1', '2017-12-13 00:00:29', '', '0000-00-00', '', '0000-00-00 00:00:00', 1, '', 0, 0, '0', 'pm1', '2017-12-13 00:10:24', 'pass'), +(2, 2, 0, 0, 8, 0, 10, 1, 'SEO setup test', '', '', 2, 'feature', ',feature', '', '', '0000-00-00', '', '', 'normal', '', '1', 0, 'pm1', '2017-12-13 00:04:09', '', '0000-00-00', 'pm1', '2017-12-13 00:18:17', 2, '', 0, 0, '0', 'pm1', '2017-12-13 00:23:48', 'fail'), +(3, 2, 0, 0, 8, 0, 0, 1, 'general setup test', '', '', 3, 'feature', '', '', '', '0000-00-00', '', '', 'normal', '', '1', 0, 'pm1', '2017-12-13 00:13:25', '', '0000-00-00', '', '0000-00-00 00:00:00', 1, '', 0, 0, '0', '', '0000-00-00 00:00:00', ''); INSERT INTO `zt_casestep` (`id`, `parent`, `case`, `version`, `type`, `desc`, `expect`) VALUES (1, 0, 1, 1, 'step', 'Switch on cache.', 'Cache is on.'), @@ -159,15 +159,15 @@ INSERT INTO `zt_history` (`id`, `action`, `field`, `old`, `new`, `diff`) VALUES (1, 7, 'desc', 'Finish developing system drive program.', 'Add advanced features such as remote desktop.', '001- Finish developing system drive program.\n001+ Add advanced features such as remote desktop.'), (2, 8, 'desc', 'Finish developing general features.
', 'Finish developing general features for users.
', '001- Finish developing features that are often used.
\n001+ Finish developing general features for users.
'), (3, 27, 'realStarted', '0000-00-00', '2017-12-12', ''), -(4, 27, 'assignedTo', 'pg2', 'pm1', ''), +(4, 27, 'assignedTo', 'pm1', 'pm1', ''), (5, 27, 'status', 'wait', 'doing', ''), (6, 28, 'left', '100', '64', ''), (7, 28, 'consumed', '0', '8', ''), (8, 29, 'realStarted', '0000-00-00', '2017-12-12', ''), -(9, 29, 'assignedTo', 'pg2', 'pm1', ''), +(9, 29, 'assignedTo', 'pm1', 'pm1', ''), (10, 29, 'status', 'wait', 'doing', ''), (11, 30, 'realStarted', '0000-00-00', '2017-12-12', ''), -(12, 30, 'assignedTo', 'pg3', 'pm1', ''), +(12, 30, 'assignedTo', 'pm1', 'pm1', ''), (13, 30, 'status', 'wait', 'doing', ''), (14, 31, 'left', '60', '0', ''), (15, 31, 'consumed', '0', '60', ''), @@ -183,11 +183,11 @@ INSERT INTO `zt_history` (`id`, `action`, `field`, `old`, `new`, `diff`) VALUES (25, 79, 'realStarted', '0000-00-00', '2017-12-12', ''), (26, 79, 'status', 'wait', 'doing', ''), (27, 80, 'consumed', '0', '30', ''), -(28, 80, 'assignedTo', 'pg1', 'pm1', ''), +(28, 80, 'assignedTo', 'pm1', 'pm1', ''), (29, 80, 'finishedDate', '', '2017-12-12 23:47:37', ''), (30, 80, 'left', '40', '0', ''), (31, 80, 'status', 'doing', 'done', ''), -(32, 80, 'finishedBy', '', 'pg1', ''), +(32, 80, 'finishedBy', '', 'pm1', ''), (33, 84, 'left', '60', '50', ''), (34, 84, 'consumed', '0', '8', ''), (35, 87, 'pri', '3', '2', ''), @@ -215,8 +215,8 @@ INSERT INTO `zt_module` (`id`, `root`, `branch`, `name`, `parent`, `path`, `grad (10, 2, 0, 'Manage Articles', 7, ',7,10,', 2, 30, 'story', '', '', '0'); INSERT INTO `zt_product` (`id`, `name`, `code`, `line`, `type`, `status`, `desc`, `PO`, `QD`, `RD`, `acl`, `whitelist`, `createdBy`, `createdDate`, `createdVersion`, `order`, `deleted`) VALUES -(1, 'windows 10', 'win10', 0, 'normal', 'normal', '', 'thePO', 'thePM', 'pg3', 'open', '', 'thePO', '2017-12-12 14:44:55', '9.6.3', 5, '0'), -(2, 'Blog', 'blog', 0, 'normal', 'normal', 'A blogging system
', 'thePO', 'theQS', 'pg3', 'open', '', 'admin', '2017-12-12 23:28:29', '9.6.3', 10, '0'); +(1, 'windows 10', 'win10', 0, 'normal', 'normal', '', 'thePO', 'pm1', 'pm1', 'open', '', 'thePO', '2017-12-12 14:44:55', '9.6.3', 5, '0'), +(2, 'Blog', 'blog', 0, 'normal', 'normal', 'A blogging system
', 'thePO', 'pm1', 'pm1', 'open', '', 'admin', '2017-12-12 23:28:29', '9.6.3', 10, '0'); INSERT INTO `zt_productplan` (`id`, `product`, `branch`, `title`, `desc`, `begin`, `end`, `deleted`) VALUES (1, 1, 0, 'win10 v1.0', 'Finish developing general features for users.
', '2017-12-30', '2018-07-03', '0'), @@ -285,13 +285,13 @@ INSERT INTO `zt_task` (`id`, `parent`, `project`, `module`, `story`, `storyVersi (1, 0, 1, 1, 1, 1, 0, 'Offer up to 10 desktops to users.', 'devel', 3, 100, 8, 64, '0000-00-00', 'doing', '', NULL, 'User can do different tasks on different desktops.', 'pm1', '2017-12-12 15:05:06', 'pm1', '2017-12-12 15:12:17', '0000-00-00', '2017-12-12', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 'pm1', '2017-12-12 15:13:13', '0'), (2, 0, 1, 1, 2, 1, 0, 'Custom desktop wallpaper', 'devel', 3, 80, 0, 80, '0000-00-00', 'doing', '', NULL, '', 'pm1', '2017-12-12 15:05:06', 'pm1', '2017-12-12 15:13:25', '0000-00-00', '2017-12-12', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 'pm1', '2017-12-12 15:13:25', '0'), (3, 0, 1, 1, 3, 1, 0, 'Auto classify files.', 'devel', 3, 60, 60, 0, '0000-00-00', 'done', '', NULL, '', 'pm1', '2017-12-12 15:05:06', 'pm1', '2017-12-12 15:14:47', '0000-00-00', '2017-12-12', 'pm1', '2017-12-12 15:14:47', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 'pm1', '2017-12-12 15:14:47', '0'), -(4, 0, 1, 1, 3, 1, 0, 'File type configuration', 'devel', 4, 40, 0, 40, '0000-00-00', 'wait', '', NULL, '', 'pm1', '2017-12-12 15:05:06', 'pg3', '2017-12-12 15:05:06', '0000-00-00', '0000-00-00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', '0'), -(5, 0, 2, 8, 9, 1, 0, 'General backend setup', 'devel', 3, 40, 30, 0, '0000-00-00', 'done', '', NULL, '', 'pm1', '2017-12-12 23:45:14', 'pm1', '2017-12-12 23:47:37', '0000-00-00', '2017-12-12', 'pg1', '2017-12-12 23:47:37', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 'pg1', '2017-12-12 23:47:37', '0'), -(6, 0, 2, 8, 10, 1, 0, 'backend SEO setup', 'devel', 3, 50, 0, 50, '0000-00-00', 'wait', '', NULL, 'Set SEO switch and report.', 'pm1', '2017-12-12 23:45:14', 'pg2', '2017-12-12 23:45:14', '0000-00-00', '0000-00-00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', '0'), +(4, 0, 1, 1, 3, 1, 0, 'File type configuration', 'devel', 4, 40, 0, 40, '0000-00-00', 'wait', '', NULL, '', 'pm1', '2017-12-12 15:05:06', 'pm1', '2017-12-12 15:05:06', '0000-00-00', '0000-00-00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', '0'), +(5, 0, 2, 8, 9, 1, 0, 'General backend setup', 'devel', 3, 40, 30, 0, '0000-00-00', 'done', '', NULL, '', 'pm1', '2017-12-12 23:45:14', 'pm1', '2017-12-12 23:47:37', '0000-00-00', '2017-12-12', 'pm1', '2017-12-12 23:47:37', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 'pm1', '2017-12-12 23:47:37', '0'), +(6, 0, 2, 8, 10, 1, 0, 'backend SEO setup', 'devel', 3, 50, 0, 50, '0000-00-00', 'wait', '', NULL, 'Set SEO switch and report.', 'pm1', '2017-12-12 23:45:14', 'pm1', '2017-12-12 23:45:14', '0000-00-00', '0000-00-00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', '0'), (7, 0, 2, 8, 11, 1, 0, 'backend cache setup', 'devel', 3, 30, 8, 55, '0000-00-00', 'doing', '', NULL, 'Set cache switch and time.', 'pm1', '2017-12-12 23:45:14', 'pm1', '2017-12-12 23:45:53', '0000-00-00', '2017-12-12', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 'pm1', '2017-12-12 23:45:53', '0'), (8, 0, 2, 8, 12, 1, 0, 'backend security setup', 'devel', 3, 30, 0, 30, '0000-00-00', 'doing', '', NULL, '', 'pm1', '2017-12-12 23:45:14', 'pm1', '2017-12-12 23:45:14', '0000-00-00', '2017-12-12', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 'pm1', '2017-12-12 23:45:35', '0'), -(9, 0, 2, 9, 13, 1, 0, 'backend UI setup', 'devel', 3, 60, 8, 50, '0000-00-00', 'doing', '', NULL, '', 'pm1', '2017-12-12 23:45:14', 'pg1', '2017-12-12 23:45:14', '0000-00-00', '2017-12-12', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 'pg3', '2017-12-12 23:51:14', '0'), -(10, 0, 2, 6, 14, 1, 0, 'Page display', 'devel', 3, 60, 0, 60, '0000-00-00', 'wait', '', NULL, '', 'pm1', '2017-12-12 23:45:14', 'pg2', '2017-12-12 23:45:14', '0000-00-00', '0000-00-00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', '0'); +(9, 0, 2, 9, 13, 1, 0, 'backend UI setup', 'devel', 3, 60, 8, 50, '0000-00-00', 'doing', '', NULL, '', 'pm1', '2017-12-12 23:45:14', 'pm1', '2017-12-12 23:45:14', '0000-00-00', '2017-12-12', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 'pm1', '2017-12-12 23:51:14', '0'), +(10, 0, 2, 6, 14, 1, 0, 'Page display', 'devel', 3, 60, 0, 60, '0000-00-00', 'wait', '', NULL, '', 'pm1', '2017-12-12 23:45:14', 'pm1', '2017-12-12 23:45:14', '0000-00-00', '0000-00-00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', '0'); INSERT INTO `zt_taskestimate` (`id`, `task`, `date`, `left`, `consumed`, `account`, `work`) VALUES (1, 1, '2017-12-12', 100, 0, 'pm1', NULL), @@ -301,55 +301,37 @@ INSERT INTO `zt_taskestimate` (`id`, `task`, `date`, `left`, `consumed`, `accoun (5, 3, '2017-12-12', 0, 60, 'pm1', 'Finish'), (6, 8, '2017-12-12', 30, 0, 'pm1', NULL), (7, 7, '2017-12-12', 55, 8, 'pm1', ''), -(8, 9, '2017-12-12', 60, 0, 'pg1', NULL), -(9, 5, '2017-12-12', 40, 0, 'pg1', NULL), -(10, 5, '2017-12-12', 0, 30, 'pg1', NULL), -(11, 9, '2017-12-13', 50, 8, 'pg3', 'Finish page design'); +(8, 9, '2017-12-12', 60, 0, 'pm1', NULL), +(9, 5, '2017-12-12', 40, 0, 'pm1', NULL), +(10, 5, '2017-12-12', 0, 30, 'pm1', NULL), +(11, 9, '2017-12-13', 50, 8, 'pm1', 'Finish page design'); -INSERT INTO `zt_team` (`project`, `task`, `account`, `role`, `limited`, `join`, `days`, `hours`, `estimate`, `consumed`, `left`, `order`) VALUES -(1, 0, 'thePO', 'Product Owner', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0), -(1, 0, 'pm1', 'Project Manager', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0), -(1, 0, 'pg2', 'Developer', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0), -(1, 0, 'pg3', 'Developer', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0), -(1, 0, 'qa1', 'Tester', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0), -(2, 0, 'pm1', 'Project Manager', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0), -(2, 0, 'pg1', 'Developer', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0), -(2, 0, 'pg2', 'Developer', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0), -(2, 0, 'pg3', 'Developer', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0); +INSERT INTO `zt_team` (`root`, `type`, `account`, `role`, `limited`, `join`, `days`, `hours`, `estimate`, `consumed`, `left`, `order`) VALUES +(2, 'project', 'thePO', 'Product Owner', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0), +(2, 'project', 'pm1', 'Project Manager', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0), +(1, 'project', 'thePO', 'Product Owner', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0), +(1, 'project', 'pm1', 'Project Manager', 'no', '2017-12-12', 10, 7.0, 0.00, 0.00, 0.00, 0); INSERT INTO `zt_testresult` (`id`, `run`, `case`, `version`, `caseResult`, `stepResults`, `lastRunner`, `date`) VALUES -(1, 1, 2, 1, 'fail', 'a:3:{i:3;a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}i:4;a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:24:\"Not all 400 page is displayed.\";}i:5;a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}}', 'qa1', '2017-12-13 00:08:52'), -(2, 2, 1, 1, 'pass', 'a:2:{i:1;a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}i:2;a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}}', 'qa1', '2017-12-13 00:10:24'), -(3, 0, 2, 2, 'fail', 'a:4:{i:7;a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:42:\"‘Contact Us’ page is missing in sitemap.\";}i:8;a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:36:\"400 page is missing.‘/notExitPage’;\";}i:9;a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}i:10;a:2:{s:6:\"result\";s:3:\"n/a\";s:4:\"real\";s:45:\"Blogroll cannot be added, and database error prompts.\";}}', 'qa1', '2017-12-13 00:23:41'), -(4, 0, 2, 2, 'fail', 'a:4:{i:7;a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:42:\"‘Contact Us’ page is missing in sitemap.\";}i:8;a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:36:\"400 page is missing.‘/notExitPage’;\";}i:9;a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}i:10;a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:45:\"Blogroll cannot be added, and database error prompts.\";}}', 'qa1', '2017-12-13 00:23:48'); +(1, 1, 2, 1, 'fail', 'a:3:{i:3;a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}i:4;a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:24:\"Not all 400 page is displayed.\";}i:5;a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}}', 'pm1', '2017-12-13 00:08:52'), +(2, 2, 1, 1, 'pass', 'a:2:{i:1;a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}i:2;a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}}', 'pm1', '2017-12-13 00:10:24'), +(3, 0, 2, 2, 'fail', 'a:4:{i:7;a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:42:\"‘Contact Us’ page is missing in sitemap.\";}i:8;a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:36:\"400 page is missing.‘/notExitPage’;\";}i:9;a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}i:10;a:2:{s:6:\"result\";s:3:\"n/a\";s:4:\"real\";s:45:\"Blogroll cannot be added, and database error prompts.\";}}', 'pm1', '2017-12-13 00:23:41'), +(4, 0, 2, 2, 'fail', 'a:4:{i:7;a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:42:\"‘Contact Us’ page is missing in sitemap.\";}i:8;a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:36:\"400 page is missing.‘/notExitPage’;\";}i:9;a:2:{s:6:\"result\";s:4:\"pass\";s:4:\"real\";s:0:\"\";}i:10;a:2:{s:6:\"result\";s:4:\"fail\";s:4:\"real\";s:45:\"Blogroll cannot be added, and database error prompts.\";}}', 'pm1', '2017-12-13 00:23:48'); INSERT INTO `zt_testrun` (`id`, `task`, `case`, `version`, `assignedTo`, `lastRunner`, `lastRunDate`, `lastRunResult`, `status`) VALUES -(1, 1, 2, 2, 'theQS', 'qa1', '2017-12-13 00:08:52', 'fail', 'done'), -(2, 1, 1, 1, 'qa1', 'qa1', '2017-12-13 00:10:24', 'pass', 'done'); +(1, 1, 2, 2, 'pm1', 'pm1', '2017-12-13 00:08:52', 'fail', 'done'), +(2, 1, 1, 1, 'pm1', 'pm1', '2017-12-13 00:10:24', 'pass', 'done'); INSERT INTO `zt_testsuite` (`id`, `product`, `name`, `desc`, `type`, `addedBy`, `addedDate`, `lastEditedBy`, `lastEditedDate`, `deleted`) VALUES -(1, 2, 'Testsuite', 'Testsuite', 'public', 'qa1', '2017-12-13 00:05:13', '', '0000-00-00 00:00:00', '0'); +(1, 2, 'Testsuite', 'Testsuite', 'public', 'pm1', '2017-12-13 00:05:13', '', '0000-00-00 00:00:00', '0'); INSERT INTO `zt_testtask` (`id`, `name`, `product`, `project`, `build`, `owner`, `pri`, `begin`, `end`, `mailto`, `desc`, `report`, `status`, `deleted`) VALUES (1, 'test for blog v0.1', 2, 2, '2', 'thePO', 0, '2018-01-05', '2018-01-20', '', '', '', 'wait', '0'); INSERT INTO `zt_user` (`dept`, `account`, `password`, `role`, `realname`, `nickname`, `commiter`, `avatar`, `birthday`, `gender`, `email`, `skype`, `qq`, `yahoo`, `gtalk`, `wangwang`, `mobile`, `phone`, `address`, `zipcode`, `join`, `visits`, `ip`, `last`, `fails`, `locked`, `ranzhi`, `score`, `scoreLevel`, `deleted`) VALUES (1, 'thePO', 'e10adc3949ba59abbe56e057f20f883e', 'po', 'Richard', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 3, '127.0.0.1', 1513093950, 0, '0000-00-00 00:00:00', '', 0, 0, '0'), -(5, 'pm1', 'e10adc3949ba59abbe56e057f20f883e', 'pm', 'Daniel', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 2, '127.0.0.1', 1513093318, 0, '0000-00-00 00:00:00', '', 0, 0, '0'), -(6, 'pm2', 'e10adc3949ba59abbe56e057f20f883e', 'pm', 'Matthew', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 0, '', 0, 0, '0000-00-00 00:00:00', '', 0, 0, '0'), -(5, 'pg1', 'e10adc3949ba59abbe56e057f20f883e', 'dev', 'Mark', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 1, '127.0.0.1', 1513093595, 0, '0000-00-00 00:00:00', '', 0, 0, '0'), -(5, 'pg2', 'e10adc3949ba59abbe56e057f20f883e', 'dev', 'Andrew', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 0, '', 0, 0, '0000-00-00 00:00:00', '', 0, 0, '0'), -(5, 'pg3', 'e10adc3949ba59abbe56e057f20f883e', 'dev', 'Jean', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 2, '127.0.0.1', 1513094149, 0, '0000-00-00 00:00:00', '', 0, 0, '0'), -(3, 'thePM', 'e10adc3949ba59abbe56e057f20f883e', 'qd', 'Tracy', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 0, '', 0, 0, '0000-00-00 00:00:00', '', 0, 0, '1'), -(3, 'qa1', 'e10adc3949ba59abbe56e057f20f883e', 'qa', 'Robert', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', 'admin', '0000-00-00', 2, '127.0.0.1', 1513094253, 0, '0000-00-00 00:00:00', '', 0, 0, '0'), -(3, 'theQS', 'e10adc3949ba59abbe56e057f20f883e', 'qd', 'Hannah', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 1, '127.0.0.1', 1513063356, 0, '0000-00-00 00:00:00', '', 0, 0, '0'); +(5, 'pm1', 'e10adc3949ba59abbe56e057f20f883e', 'pm', 'Daniel', '', '', '', '0000-00-00', 'm', '', '', '', '', '', '', '', '', '', '', '0000-00-00', 2, '127.0.0.1', 1513093318, 0, '0000-00-00 00:00:00', '', 0, 0, '0'); INSERT INTO `zt_usergroup` (`account`, `group`) VALUES -('pg1', 2), -('pg2', 2), -('pg3', 2), ('pm1', 4), -('pm2', 4), -('qa1', 3), -('thePM', 8), ('thePO', 5); diff --git a/db/update9.7.sql b/db/update9.7.sql new file mode 100644 index 0000000000..0757cd8f41 --- /dev/null +++ b/db/update9.7.sql @@ -0,0 +1,33 @@ +ALTER TABLE `zt_story` CHANGE `stage` `stage` ENUM('','wait','planned','projected','developing','developed','testing','tested','verified','released','closed') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'wait'; +ALTER TABLE `zt_todo` ADD `config` varchar(255) NOT NULL; +ALTER TABLE `zt_todo` ADD `cycle` tinyint unsigned NOT NULL DEFAULT '0' AFTER `type`; +ALTER TABLE `zt_todo` ADD `assignedTo` VARCHAR(30) NOT NULL DEFAULT '' AFTER `config`; +ALTER TABLE `zt_todo` ADD `assignedBy` VARCHAR(30) NOT NULL DEFAULT '' AFTER `assignedTo`; +ALTER TABLE `zt_todo` ADD `assignedDate` DATETIME NOT NULL AFTER `assignedBy`; +ALTER TABLE `zt_todo` ADD `finishedBy` VARCHAR(30) NOT NULL DEFAULT '' AFTER `assignedDate`; +ALTER TABLE `zt_todo` ADD `finishedDate` DATETIME NOT NULL AFTER `finishedBy`; +ALTER TABLE `zt_todo` ADD `closedBy` VARCHAR(30) NOT NULL DEFAULT '' AFTER `finishedDate`; +ALTER TABLE `zt_todo` ADD `closedDate` DATETIME NOT NULL AFTER `closedBy`; +ALTER TABLE `zt_todo` CHANGE `status` `status` ENUM('wait','doing','done','closed') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'wait'; + +INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`, `lastTime`) VALUES +('1', '1', '*', '*', '*', 'moduleName=todo&methodName=createCycle', '生成周期性待办', 'zentao', 1, 'normal', '0000-00-00 00:00:00'); + + +ALTER TABLE `zt_projectproduct` ADD `plan` MEDIUMINT(8) UNSIGNED NOT NULL AFTER `branch`; + +CREATE TABLE IF NOT EXISTS `zt_notify` ( + `id` mediumint unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, + `objectType` varchar(50) NOT NULL, + `objectID` mediumint unsigned NOT NULL, + `action` mediumint NOT NULL, + `toList` varchar(255) NOT NULL, + `ccList` text NOT NULL, + `subject` varchar(255) NOT NULL, + `data` text NOT NULL, + `createdBy` char(30) NOT NULL, + `createdDate` datetime NOT NULL, + `sendTime` datetime NOT NULL, + `status` varchar(10) NOT NULL DEFAULT 'wait', + `failReason` text NOT NULL +) ENGINE='MyISAM' COLLATE 'utf8_general_ci'; diff --git a/db/zentao.sql b/db/zentao.sql index bafc633bfb..c3180eb72f 100644 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -407,12 +407,28 @@ CREATE TABLE IF NOT EXISTS `zt_module` ( PRIMARY KEY (`id`), KEY `module` (`root`,`type`,`path`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; +-- DROP TABLE IF EXISTS `zt_notify`; +CREATE TABLE IF NOT EXISTS `zt_notify` ( + `id` mediumint unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY, + `objectType` varchar(50) NOT NULL, + `objectID` mediumint unsigned NOT NULL, + `action` mediumint NOT NULL, + `toList` varchar(255) NOT NULL, + `ccList` text NOT NULL, + `subject` varchar(255) NOT NULL, + `data` text NOT NULL, + `createdBy` char(30) NOT NULL, + `createdDate` datetime NOT NULL, + `sendTime` datetime NOT NULL, + `status` varchar(10) NOT NULL DEFAULT 'wait', + `failReason` text NOT NULL +) ENGINE='MyISAM' COLLATE 'utf8_general_ci'; -- DROP TABLE IF EXISTS `zt_product`; CREATE TABLE IF NOT EXISTS `zt_product` ( `id` mediumint(8) unsigned NOT NULL auto_increment, `name` varchar(90) NOT NULL, `code` varchar(45) NOT NULL, - `line` mediumint(8) NOT NULL, + `line` mediumint(8) NOT NULL, `type` varchar(30) NOT NULL default 'normal', `status` varchar(30) NOT NULL default '', `desc` text NOT NULL, @@ -483,6 +499,7 @@ CREATE TABLE IF NOT EXISTS `zt_projectproduct` ( `project` mediumint(8) unsigned NOT NULL, `product` mediumint(8) unsigned NOT NULL, `branch` mediumint(8) unsigned NOT NULL, + `plan` mediumint(8) unsigned NOT NULL, PRIMARY KEY (`project`,`product`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_projectstory`; @@ -528,7 +545,7 @@ CREATE TABLE IF NOT EXISTS `zt_story` ( `estimate` float unsigned NOT NULL, `status` enum('','changed','active','draft','closed') NOT NULL default '', `color` char(7) NOT NULL, - `stage` enum('','wait','planned','projected','developing','developed','testing','tested','verified','released') NOT NULL DEFAULT 'wait', + `stage` enum('','wait','planned','projected','developing','developed','testing','tested','verified','released', 'closed') NOT NULL DEFAULT 'wait', `mailto` text, `openedBy` varchar(30) NOT NULL default '', `openedDate` datetime NOT NULL, @@ -627,8 +644,8 @@ CREATE TABLE IF NOT EXISTS `zt_taskestimate` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_team`; CREATE TABLE IF NOT EXISTS `zt_team` ( - `project` mediumint(8) unsigned NOT NULL default '0', - `task` mediumint(8) NOT NULL DEFAULT '0', + `root` mediumint(8) unsigned NOT NULL default '0', + `type` enum('project','task') NOT NULL DEFAULT 'project', `account` char(30) NOT NULL default '', `role` char(30) NOT NULL default '', `limited` char(8) NOT NULL default 'no', @@ -638,9 +655,8 @@ CREATE TABLE IF NOT EXISTS `zt_team` ( `estimate` DECIMAL(12,2) UNSIGNED NOT NULL DEFAULT '0', `consumed` DECIMAL(12,2) UNSIGNED NOT NULL DEFAULT '0', `left` DECIMAL(12,2) UNSIGNED NOT NULL DEFAULT '0', - `order` TINYINT(3) NOT NULL DEFAULT '0', - PRIMARY KEY (`project`, `task`, `account`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; + `order` TINYINT(3) NOT NULL DEFAULT '0' + ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_testreport`; CREATE TABLE IF NOT EXISTS `zt_testreport` ( `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, @@ -699,11 +715,11 @@ CREATE TABLE IF NOT EXISTS `zt_testsuite` ( `desc` text NOT NULL, `type` varchar(20) NOT NULL, `addedBy` char(30) NOT NULL, - `addedDate` datetime NOT NULL, + `addedDate` datetime NOT NULL, `lastEditedBy` char(30) NOT NULL, - `lastEditedDate` datetime NOT NULL, + `lastEditedDate` datetime NOT NULL, `deleted` enum('0','1') NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_testtask`; CREATE TABLE IF NOT EXISTS `zt_testtask` ( @@ -726,19 +742,28 @@ CREATE TABLE IF NOT EXISTS `zt_testtask` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_todo`; CREATE TABLE IF NOT EXISTS `zt_todo` ( - `id` mediumint(8) unsigned NOT NULL auto_increment, + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, `account` char(30) NOT NULL, `date` date NOT NULL, `begin` smallint(4) unsigned zerofill NOT NULL, `end` smallint(4) unsigned zerofill NOT NULL, `type` char(10) NOT NULL, - `idvalue` mediumint(8) unsigned NOT NULL default '0', + `cycle` tinyint(3) unsigned NOT NULL DEFAULT '0', + `idvalue` mediumint(8) unsigned NOT NULL DEFAULT '0', `pri` tinyint(3) unsigned NOT NULL, `name` char(150) NOT NULL, `desc` text NOT NULL, - `status` enum('wait','doing','done') NOT NULL DEFAULT 'wait', + `status` enum('wait','doing','done','closed') NOT NULL DEFAULT 'wait', `private` tinyint(1) NOT NULL, - PRIMARY KEY (`id`), + `config` varchar(255) NOT NULL, + `assignedTo` varchar(30) NOT NULL DEFAULT '', + `assignedBy` varchar(30) NOT NULL DEFAULT '', + `assignedDate` datetime NOT NULL, + `finishedBy` varchar(30) NOT NULL DEFAULT '', + `finishedDate` datetime NOT NULL, + `closedBy` varchar(30) NOT NULL DEFAULT '', + `closedDate` datetime NOT NULL, + PRIMARY KEY (`id`), KEY `todo` (`account`,`date`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_user`; @@ -771,7 +796,7 @@ CREATE TABLE IF NOT EXISTS `zt_user` ( `fails` tinyint(5) NOT NULL default '0', `locked` datetime NOT NULL default '0000-00-00 00:00:00', `ranzhi` char(30) NOT NULL default '', - `score` INT(12) NOT NULL DEFAULT '0', + `score` INT(11) NOT NULL DEFAULT '0', `scoreLevel` INT(11) NOT NULL DEFAULT '0', `deleted` enum('0','1') NOT NULL default '0', PRIMARY KEY (`id`), @@ -903,7 +928,8 @@ INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type ('30', '0', '*', '*', '*', 'moduleName=backup&methodName=backup', '备份数据和附件', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), ('*/5', '*', '*', '*', '*', 'moduleName=mail&methodName=asyncSend', '异步发信', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), ('*/5', '*', '*', '*', '*', 'moduleName=webhook&methodName=asyncSend', '异步发送Webhook', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), -('*/5', '*', '*', '*', '*', 'moduleName=admin&methodName=deleteLog', '删除过期日志', 'zentao', 1, 'normal', '0000-00-00 00:00:00'); +('*/5', '*', '*', '*', '*', 'moduleName=admin&methodName=deleteLog', '删除过期日志', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), +('1', '1', '*', '*', '*', 'moduleName=todo&methodName=createCycle', '生成周期性待办', 'zentao', 1, 'normal', '0000-00-00 00:00:00'); INSERT INTO `zt_group` (`id`, `name`, `role`, `desc`) VALUES (1, 'ADMIN', 'admin', 'for administrator'), @@ -1062,6 +1088,8 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (1, 'mail', 'reset'), (1, 'mail', 'save'), (1, 'mail', 'test'), +(1, 'message', 'index'), +(1, 'message', 'setting'), (1, 'misc', 'ping'), (1, 'my', 'bug'), (1, 'my', 'changePassword'), @@ -1129,6 +1157,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (1, 'project', 'index'), (1, 'project', 'all'), (1, 'project', 'linkStory'), +(1, 'project', 'importPlanStories'), (1, 'project', 'manageMembers'), (1, 'project', 'manageProducts'), (1, 'project', 'order'), @@ -1292,6 +1321,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (1, 'todo', 'batchEdit'), (1, 'todo', 'batchFinish'), (1, 'todo', 'create'), +(1, 'todo', 'createCycle'), (1, 'todo', 'delete'), (1, 'todo', 'edit'), (1, 'todo', 'export'), @@ -1486,12 +1516,16 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (2, 'todo', 'batchEdit'), (2, 'todo', 'batchFinish'), (2, 'todo', 'create'), +(2, 'todo', 'createCycle'), (2, 'todo', 'delete'), (2, 'todo', 'edit'), (2, 'todo', 'export'), (2, 'todo', 'finish'), (2, 'todo', 'import2Today'), (2, 'todo', 'view'), +(2, 'todo', 'assignTo'), +(2, 'todo', 'activate'), +(2, 'todo', 'close'), (2, 'user', 'bug'), (2, 'user', 'deleteContacts'), (2, 'user', 'dynamic'), @@ -1701,6 +1735,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (3, 'todo', 'batchEdit'), (3, 'todo', 'batchFinish'), (3, 'todo', 'create'), +(3, 'todo', 'createCycle'), (3, 'todo', 'delete'), (3, 'todo', 'edit'), (3, 'todo', 'export'), @@ -1838,6 +1873,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (4, 'project', 'index'), (4, 'project', 'all'), (4, 'project', 'linkStory'), +(4, 'project', 'importPlanStories'), (4, 'project', 'manageMembers'), (4, 'project', 'manageProducts'), (4, 'project', 'order'), @@ -1925,12 +1961,16 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (4, 'todo', 'batchEdit'), (4, 'todo', 'batchFinish'), (4, 'todo', 'create'), +(4, 'todo', 'createCycle'), (4, 'todo', 'delete'), (4, 'todo', 'edit'), (4, 'todo', 'export'), (4, 'todo', 'finish'), (4, 'todo', 'import2Today'), (4, 'todo', 'view'), +(4, 'todo', 'assignTo'), +(4, 'todo', 'activate'), +(4, 'todo', 'close'), (4, 'tree', 'browse'), (4, 'tree', 'browseTask'), (4, 'tree', 'delete'), @@ -2078,6 +2118,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (5, 'project', 'index'), (5, 'project', 'all'), (5, 'project', 'linkStory'), +(5, 'project', 'importPlanStories'), (5, 'project', 'manageMembers'), (5, 'project', 'manageProducts'), (5, 'project', 'order'), @@ -2182,12 +2223,16 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (5, 'todo', 'batchEdit'), (5, 'todo', 'batchFinish'), (5, 'todo', 'create'), +(5, 'todo', 'createCycle'), (5, 'todo', 'delete'), (5, 'todo', 'edit'), (5, 'todo', 'export'), (5, 'todo', 'finish'), (5, 'todo', 'import2Today'), (5, 'todo', 'view'), +(5, 'todo', 'assignTo'), +(5, 'todo', 'activate'), +(5, 'todo', 'close'), (5, 'tree', 'browse'), (5, 'tree', 'browseTask'), (5, 'tree', 'delete'), @@ -2326,6 +2371,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (6, 'project', 'index'), (6, 'project', 'all'), (6, 'project', 'linkStory'), +(6, 'project', 'importPlanStories'), (6, 'project', 'manageMembers'), (6, 'project', 'manageProducts'), (6, 'project', 'order'), @@ -2411,12 +2457,16 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (6, 'todo', 'batchEdit'), (6, 'todo', 'batchFinish'), (6, 'todo', 'create'), +(6, 'todo', 'createCycle'), (6, 'todo', 'delete'), (6, 'todo', 'edit'), (6, 'todo', 'export'), (6, 'todo', 'finish'), (6, 'todo', 'import2Today'), (6, 'todo', 'view'), +(6, 'todo', 'assignTo'), +(6, 'todo', 'activate'), +(6, 'todo', 'close'), (6, 'tree', 'browse'), (6, 'tree', 'browseTask'), (6, 'tree', 'delete'), @@ -2554,6 +2604,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (7, 'project', 'index'), (7, 'project', 'all'), (7, 'project', 'linkStory'), +(7, 'project', 'importPlanStories'), (7, 'project', 'manageProducts'), (7, 'project', 'story'), (7, 'project', 'task'), @@ -2652,12 +2703,16 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (7, 'todo', 'batchEdit'), (7, 'todo', 'batchFinish'), (7, 'todo', 'create'), +(7, 'todo', 'createCycle'), (7, 'todo', 'delete'), (7, 'todo', 'edit'), (7, 'todo', 'export'), (7, 'todo', 'finish'), (7, 'todo', 'import2Today'), (7, 'todo', 'view'), +(7, 'todo', 'assignTo'), +(7, 'todo', 'activate'), +(7, 'todo', 'close'), (7, 'tree', 'browse'), (7, 'tree', 'browseTask'), (7, 'tree', 'delete'), @@ -2905,12 +2960,16 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (8, 'todo', 'batchEdit'), (8, 'todo', 'batchFinish'), (8, 'todo', 'create'), +(8, 'todo', 'createCycle'), (8, 'todo', 'delete'), (8, 'todo', 'edit'), (8, 'todo', 'export'), (8, 'todo', 'finish'), (8, 'todo', 'import2Today'), (8, 'todo', 'view'), +(8, 'todo', 'assignTo'), +(8, 'todo', 'activate'), +(8, 'todo', 'close'), (8, 'tree', 'browse'), (8, 'tree', 'browseTask'), (8, 'tree', 'delete'), @@ -3071,12 +3130,16 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (9, 'todo', 'batchEdit'), (9, 'todo', 'batchFinish'), (9, 'todo', 'create'), +(9, 'todo', 'createCycle'), (9, 'todo', 'delete'), (9, 'todo', 'edit'), (9, 'todo', 'export'), (9, 'todo', 'finish'), (9, 'todo', 'import2Today'), (9, 'todo', 'view'), +(9, 'todo', 'assignTo'), +(9, 'todo', 'activate'), +(9, 'todo', 'close'), (9, 'user', 'batchCreate'), (9, 'user', 'batchEdit'), (9, 'user', 'bug'), @@ -3185,12 +3248,16 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (10, 'todo', 'batchEdit'), (10, 'todo', 'batchFinish'), (10, 'todo', 'create'), +(10, 'todo', 'createCycle'), (10, 'todo', 'delete'), (10, 'todo', 'edit'), (10, 'todo', 'export'), (10, 'todo', 'finish'), (10, 'todo', 'import2Today'), (10, 'todo', 'view'), +(10, 'todo', 'assignTo'), +(10, 'todo', 'activate'), +(10, 'todo', 'close'), (10, 'user', 'bug'), (10, 'user', 'dynamic'), (10, 'user', 'profile'), diff --git a/doc/CHANGELOG b/doc/CHANGELOG index 4d553aefc7..1bfeea193e 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -1,4 +1,169 @@ -2017-11-06 9.6 +2017-01-17 9.8.stable +完成的需求 +683 todo增加转需求,bug或者任务的功能 +1678 todo增加评论功能。 +1680 todo增加处理流程 +1681 待办实现周期性待办功能 +1923 报表可以选择显示的方式 +1952 移植然之里面的消息通知功能 +2001 调整导出页面的格式 +2037 测试用例关联需求时候关闭需求也列出 +2103 禅道中所有创建编辑页面的下拉框都增加搜索定位功能 +2120 需求任务bug编辑页面抄送给字段可以选择联系人 +2151 加强计划和项目之间的关系 +2243 测试版本的用例列表增加按照指派给分组。 +2245 统计-组织-员工负载表显示未安排任务的人员信息 +2339 增加指派给我的区块 +2369 处理下目标服务器积极拒绝链接的错误提示 +2380 生成测试报告时可以选择多个测试单 +2401 利用浏览器的消息提醒机制实现消息提醒 +2409 每日提醒邮件增加任务和bug的超时提醒内容 +2426 优化文档详情页面的排版 +2428 邮件中需求任务bug用例标题显示设置的颜色 +2460 Bug导入模版中增加截止日期字段的导入 +2479 zt_mailqueue 和 zt_webhookdatas 合并成zt_notify +2484 zt_team增加type和root字段,project和task 改成 root +2499 实现集中的消息处理机制 +2523 补充最近的修改记录 +2566 config下面的配置文件,应该最后加载my.php +2568 搜索表单的字段也可以支持搜索 +2572 通过编辑修改需求plan的时候,计算需求的stage字段。 +2573 计划的日期可以设置为待定 +2574 需求关闭之后,stage也都改成closed。 +2575 丰富计划列表页面的信息 +2591 help/changeLog的页面中,显示最新的changeLog +2592 修改‘个人档案’中的翻译 + +修复的Bug +1331 项目需求下,如果需求排序权限处于未开启的情况;在选择多个复选框是会出问题 +1341 点击任务开始剩余工时选择0点击确定完成任务的时候没有把指派人更换成创建人 +1343 待评审状态用例,批量编辑后,状态会更新为空 +1347 bug编辑日期可以输入汉字且被保存 +1355 zentaopms/module/dev/model.php 代码优化 +1359 看板,未开始的任务,不能拖拽到进行中。 +1360 未完全修改#2518需求中的所有项目 +1362 创建子任务使用粘贴文本,保存超过10条时,10条以上的数据不保存 +1363 后台自定义日期必填项无效 +1365 后台-安全,设置密码安全为强时,满足安全强度,登录时也会提示密码强度小 +1367 我的地盘-任务,子任务在任务列表中不显示标签 +1369 备注权限(action comment),取消视图维护,后台权限验证。 +1371 文件格式附件预览的时候报错 +1373 编辑多人任务,可以选择出了项目团队成员之外的其他成员。 +1374 多人任务,完成,转交,指派人,可以选择非项目团队成员 +1377 用例内容包含特殊字符时,导出内容不正确 +1378 编辑用户信息,填写邮箱有空格会提示email不合法 +1379 任务列表,任务条数大于每页显示条数时,新建子任务会显示在最后一页 +1382 php7 打开项目中的树状图报错 字符串转数组问题 +1384 项目-测试 操作栏中的测试报告按钮点击后跳转到创建报告页面 +1385 测试-用例 从用例库导入用例的搜索中所属模块显示的不是用例库中的模块 +1386 项目任务列表的优先级显示错误 +1387 后台-自定义-需求-评审流程,设置强制评审人员,保存不上 +1388 修改父子任务的所属项目无法整体移动 + +2017-12-22 9.7.stable +完成的需求 +2475 批量操作时增加列中切换快捷键支持 +2496 英文专业版中部分画面带有中文字符 +2515 调整国际版的发信功能 +2514 打包一个国际版的安装包 +2537 The report of bug resolve里面没有做翻译 +2532 英文版一键安装包里面需要跳转 +2530 翻译国际版一键安装包的英文界面 +2558 修正两个画面的翻译 +2557 修正五个画面的排版细节 +2556 修正 “修改密码”画面的排版问题 +2555 修正 “产品动态”和“项目动态“的中的汉字 +2547 修正 “查看项目画面”的排版问题 +2546 修正 “BUG的自定义画面“的排版问题 +2545 修正 “创建项目文档库”画面的提示框翻译 +2544 修正一键安装包中“ 报表/自定义/项目 ”的空缺内容 +2543 调整报表模块界面的列显示,消除列名显示不全 +2542 调整添加用户界面,输入提示显示不全 +2541 调整一键安装包英文界面下,做系统备份成功时的英文翻译 +2524 将国际版筛选标签里面和我相关的菜单折叠到一个My标签里面 +2520 需求详情的用例按钮中间增加空格 +2519 调整国际版下面的每个表单保证控件组的对齐 +2518 调整后台首页国际版下面的内容和链接 +2509 测试视图主页,点击待测版本区块more,可以跳转到测试-测试单下 +2506 受限操作分组维护分组描述 +2493 需求、任务、bug、用例、日志列表勾选左下方全选,导出数据时选择选中记录,可以导出全选的数据 +2492 任务列表下方统计信息,显示子任务的统计信息 +2474 需求的批量编辑画面,布局有问题,未利用所有的屏幕宽度 +2355 自定义列表字段把能够展示的字段都梳理一遍 +2351 调整后台首页和关于页面的链接 +2297 计划或者项目创建需求的时候可以批量创建 +2527 bug状态已解决翻译有误 +2516 精简一级导航菜单的单词 +2513 创建英文版本的demo +2487 编辑webhook页面,把类型字段显示出来 +2463 后台增加对 tmp和session目录读写权限检查和结果展示的功能 +2553 历史记录里面的旧记录翻译需要修改 +2552 优化国际版下面页脚统计信息的翻译 +2551 创建计划时日期选择翻译错了 +2550 计划关联需求的翻译弄反了 +2549 需求关闭页面closed reaseon换行 +2540 调整需求创建时推荐模板的翻译 +2539 各个统计报表的翻译需要调整 +2538 公司视图的统计需要调整翻译。 +2536 国际版去掉用不到的bug类型 +2535 调整国际版里面的网站链接 +2534 调整权限分组里面的翻译和排版 +2531 需求变更页面翻译需要调整 +2529 bug详情页面的create应当是Copy +2528 bug创建表单keywords空间需要去掉空格 +2488 项目 任务视图,增加由我参与的任务按钮,展示由我参与的任务(多人任务)。 + +修复的BUG +1008 我的地盘首页的待办点击后跳转到组织-用户-待办页面 +1214 项目起止时间显示优化 +1219 从桌面客户端查看待办,页面显示不对。 +1221 任务报表统计中没有显示自定义的值 +1224 非多平台产品,在测试管理工作方式中,测试视图显示异常。 +1225 调用api反馈 nogdlib实际是有gd库的 +1228 手机浏览器访问开源版报错 +1232 任务、用例、bug,直接在列表下进行编辑操作,操作后底部统计栏不再固定显示 +1234 需求评审结果显示错误 +1240 提交需求会列出没有权限查看的产品名称 +1244 组织-日志中,选择本月或上月时,结束日期显示准确。 +1251 测试用例导出csv文件,报文格式数据不显示 +1255 zbox一键安装包,建议安装 aria_chk +1256 搜索条件为日期介于时间段时,搜索后点击重置,搜索条件还在,需要重新点击搜索,条件才会重置。 +1261 批量分解任务无法分配相同名称的任务 +1264 没有产品的时候打开debug,进入以下页面会产生大量警告性的错误 +1268 需求细分功能如果没有填写任何数据被细分的需求也会关闭 +1273 测试视图,bug列表,单选框无法正常单选。 +1274 开源版集成svn/git查看显示403 +1275 文档维护分类,把模块和子模块改为分类。 +1280 后台-备份在直线还原操作的时候先检查备份文件的权限是否可以正常执行还原动作 +1283 列表页面,批操作菜单,会被遮盖。建议优化。 +1292 子任务指派给用户时,用户登陆后,不会在指派给我中显示 +1305 修复邮件发送公司信息没有及时更新的问题 +1309 开启测试管理工具(产品-项目流程),多分支产品,版本根据分支筛选功能异常。 +1314 产品-需求 无法批量关闭需求 +1324 产品-需求-编辑,删除所属计划后保存不生效 +1325 windows一键安装包9.0升9.6.3,admin登录提示没首页权限 +1326 子任务关闭或删除后,父任务预计工时还会统计 +1327 任务全选,导出数据,不能导出子任务. +1328 项目概况预计工时,与燃尽图不符。 +1329 多人任务,按照指派给分组,显示优化。 +1330 项目任务,编辑任务,更换所属项目,顶部弹出窗口,点击取消;选中内容还是目标内容 +1332 保持登录功能可能失效 +1335 测试管理工具,产品--版本产品下载地址显示有问题 +1336 测试管理工具,项目--迭代,添加项目页面报错。 +1337 项目-任务按照模块和产品筛选数据有问题 +1338 后台-二次开发-数据库 --其他模块,显示英文字段 +1340 编辑bug解决日期会显示被修改 +1341 点击任务开始剩余工时选择0点击确定完成任务的时候没有把指派人更换成创建人 +1342 产品-需求列表在某个分支下无法显示所属计划 +1343 待评审状态用例,批量编辑后,状态会更新为空 +1344 测试bug,解决bug与激活bug功能,版本下拉,没有根据项目进行过滤。 +1345 多人任务都完成后没有指派给创建人 +1347 bug编辑日期可以输入汉字且被保存 +1348 子任务工时在所有项目页面,工时会统计为双倍 +1349 测试-用例列表,用例选择多个适用阶段,列表显示错行 +1350 项目任务列表,高级表格,延期任务,选中,鼠标放置上去,显示异常。 + +2017-11-06 9.6.stable 完成的需求 1988 需求,任务,bug,用例,待办都可以选择看板模式。 2004 运维性的项目支持多人任务和子任务功能 diff --git a/doc/LICENSE b/doc/LICENSE deleted file mode 100644 index ad1d7c53f5..0000000000 --- a/doc/LICENSE +++ /dev/null @@ -1,205 +0,0 @@ -Z PUBLIC LICENSE 1.2 - -许可 - -Z PUBLIC LICENSE 由青岛易软天创网络科技有限公司(www.cnezsoft.com)起草,简称ZPL协议。 -任何人均可使用该协议来发布开源软件,并可对下面协议正文中以下划线标注的空白部分做相应修改, -除此之外的任何内容不得做任何修改。青岛易软天创网络科技有限公司拥有对该协议条款的最终解释权。 - -前言: - -禅道项目管理软件(以下简称该软件)由 青岛易软天创网络科技有限公司(www.cnezsoft.com)开发(以下简称我)。我依法拥有该软件的所有版权。 -本着共享开放的角度,我以开放源代码的形式发布该软件。您可以在遵守该协议的前提下使用该软件。 -自您安装该软件开始,您和我之间的合同关系自动成立。除非您停止使用该软件或与我有签署额外合同, -您须认真遵循该授权协议约定的每一条款。 - -我的联系方式: -联系人:徐先生 -电话: 4006-8899-23 -Email: co@cnezsoft.com -QQ: 1492153927 -地址: 青岛开发区武夷山路167号千禧龙花园 9-1-101室 - -约定: - -下述条款中所指该软件的标志包括如下方面: - - 该软件源代码及文档中关于该软件的版权提示、文字、图片和链接。 - 该软件运行时界面上呈现出来的有关该软件的文字、图片和链接。 - -不包括如下方面: - - 该软件提供的演示数据中关于该软件的文字、图片和链接。 - -一、免责 - -该软件是以开放源代码的方式发行,您使用该软件无需任何费用,因此在使用该软件前,您须知晓: - - 1.1 我没有对该软件提供任何技术支持的义务,您可联系我购买商业的技术支持。 - 1.2 我对因使用该软件而产生直接或间接的任何问题不负任何责任。 - 1.3 开源不等于免费,开源不等于无版权,开源软件的发展需要您我共同的努力。 - -二、自用该软件 - -2.1 您个人或您就职的公司(组织)可自由使用该软件,我不对您或您就职公司(组织)的性质做任何限制。 -2.2 您可以在您个人或您就职公司(组织)任意数量的电脑上运行该软件,我不对电脑的数量做任何限制。 -2.3 您可以对该软件源代码进行修改以适应您个人或您所在公司(组织)使用的要求,您做的改动无需对外发布。 -2.4 您个人或您就职公司(组织)使用该软件时,必须保留该软件的所有标志,不得以任何方式隐藏或遮掩任一标志。 - -三、为用户定制 - -3.1 您可以使用该软件为您的用户部署各种形式的应用,我不对应用的性质做任何限制。 -3.2 您可以使用该软件为您的用户部署任意数量的应用,我不对应用的数量做任何限制。 -3.3 您可以对该软件源代码进行修改以适应您的用户的要求,您做的改动无需对外发布。 -3.4 您对该软件源代码所做的修改可以源代码或二进制的方式提供给您的用户。 -3.5 您使用该软件为您的任一用户部署的任一应用都必须保留该软件所有的标志。 -3.6 您使用该软件为您的任一用户部署的任一应用都不得以任何方式隐藏或遮掩该软件任一标志。 - -四、提供在线服务 - -4.1 您可以使用该软件搭建在线服务,为您的用户提供服务,我不对该服务及该服务用户的性质做任何限制。 -4.2 您可以使用该软件搭建在线服务,为您的用户提供服务,我不对该服务的用户数量做任何限制。 -4.3 您可以对该软件源代码进行修改以适应在线服务的要求,您做的改动无需对外发布。 -4.4 您使用该软件搭建在线服务时,必须以明确的方式告知您的用户该服务是基于该软件搭建的。 -4.5 您使用该软件搭建在线服务为您的任一用户部署的任一应用必须保留该软件所有的标志。 -4.6 您使用该软件搭建在线服务为您的任一用户部署的任一应用不得以任何方式隐藏或遮掩该软件任一标志。 -4.7 您使用该软件搭建在线服务时,不得为您的用户提供去除、隐藏或遮掩该软件任一标志的功能。 - -五、无改动发布或集成该软件 - -5.1 我欢迎并感谢您将该软件发布在您的个人网站、企业官网或者其他的第三方网站。 -5.2 我欢迎并感谢您将该软件集成在其他系统中一起发布,比如云服务镜像、操作系统发行版等。 -5.3 您在发布或者集成该软件的时候,不得对该软件源码做任何改动。 -5.4 您在发布或者集成该软件的时候,须保留该软件的所有标志。 - -六、发布基于该软件的衍生作品 - -6.1 我欢迎并感谢您为该软件开发衍生作品。 -6.2 您开发的衍生作品中涉及到对该软件源代码改动的地方,须遵循如下条款: - - 6.2.1 如修改了该软件的源代码,须依据本协议发布修改后的源代码。 - 6.2.2 如修改了该软件的源代码,须保留代码里面该软件原有的所有标志。 - 6.2.3 您可以在代码中追加您自己的标志。 - 6.2.4 您可以对您开发的衍生作品进行收费。 - 6.2.5 第三方的用户可在遵循6.2所有条款下可继续在您开发的衍生作品基础上进行修改并发布。 - -6.3 您开发的衍生作品中独立于本软件开发的代码,可以源代码或二进制的方式进行发布,可免费或收费发布。 -6.4 您开发的衍生作品不得以任何方式去除、隐藏或遮掩该软件的任一标志。 - -七、发布基于该软件API的应用 - -7.1 我欢迎并感谢您为该软件开发基于API的各种应用,比如客户端软件等。 -7.2 您基于该软件API机制开发的应用,可以源代码或者二进制的方式进行发布,我对此没有任何限制。 -7.3 您基于该软件API机制开发的应用,授权协议可以自行约定,我对此没有任何限制。 -7.4 您基于该软件API机制开发的应用,可以免费或者收费发布,我对此没有任何限制。 - -八、授权例外 - -如果上述条款无法满足您使用该软件的要求,可联系我签署额外的合同以获得更灵活的授权许可。 - -九、合同约束 - -9.1 如果您违反了该协议的任一条款,该授权协议将自动终止,我保留通过法律手段追究责任的权利。 - -Z PUBLIC LICENSE 1.2 - -Authorization - -Z PUBLIC LICENSE, also known as ZPL Agreement, is drafted by QingDao Nature Easy Soft Network Technology Co,LTD. (,www.cnezsoft.com). -Anyone can use the agreement to publish open source software, and modify the blank underlined part of the following text of the agreement accordingly. -No other text of the agreement shall be changed. QingDao Nature Easy Soft Network Technology Co,LTD has the final authority to interpret the terms of the agreement. - -Preface - -ZenTaoPMS (Hereinafter referred to as "the software") developed by Nature EasySoft Network Tecnology Co.ltd, QingDao, China (www.cnezsoft.com) (hereinafter referred to I). I'm entitled to all copyright of the software. -The software is released as open source software. You are authorized to use the software as long as you are in compliance with this agreement. -By installation of the software, you agree that a contractual relationship between you and me is automatically established. -You are obliged to fully comply with all the terms of this agreement unless you choose to stop using the software or you have signed additional contracts with me. - -My Contact: -Contact: Mr. Xu -Phone: 4006-8899-23 -Email: co@cnezsoft.com -QQ: 1492153927 -Address: 9-1-101, 167 Wuyishan Lu, Kai Fa Qu, Qingdao - -We agree: - -Indications of the software include: - - Notes, texts, pictures and links showing copyright attribution of the software in the source code and related documentation. - and texts, picture and links on the interface of the software when running. - -Excluding - - texts, picture and links on the interface of the demo versions of the software. - -1. Disclaimer - -The software is an open-source software, so you are authorized to use the software without paying a fee. Before you start to use it, please note: - - 1.1 I do not have any obligation to provide technical support for the software. You can contact me to purchase technical support service. - 1.2 I'm not responsible for any liability caused by your using the software directly or indirectly. - 1.3 Open source software does not mean it's free of charge, neither does it mean the software does not enjoy copyright. - -2. For personal use - -2.1 You or your company/organization are authorized to use the software for your internal use for both commercial and non-commercial purposes.. -2.2 You or your company/organization are authorized to run the software on any number of computers. -2.3 You or your company/organization are authorized to modify the source code of the software to meet your requirements. You do not need to release the modified codes. -2.4 You or your company/organization must keep all the indications of the software when using it. None of the indications can be removed, hidden or obscured in any way. - -3. For customized software - -3.1 You are authorized to use the software to deploy various forms of application for your users in any way you like. -3.2 You are authorized to use the software to deploy any number of applications for your users. -3.3 You are authorized to modify the source code to meet your user's requirements without releasing the modified codes. -3.4 You are authorized to provide the modified codes to your users in either source code form or binary. -3.5 You must keep all the indications of the software when providing applications to your users. -3.6 None of the indications of the software may be removed, hidden or obscured in any way when you provide applications to your users. - -4. Online service - -4.1 You are authorized to use the software to build your online service for your users in any way you like. -4.2 You are authorized to use the software to build your online service for any number of your users. -4.3 You are authorized to modify the source codes of the software to meet your user's requirements on online service without releasing the modified codes. -4.4 You must notify your users clearly that your service is based on the software when you use it to build your online service. -4.5 You must keep all the indications of the software when providing online service to your users. -4.6 You must keep all the indications of the software in any application you make for your users. None of the indications can be hidden or obscured in any way. -4.7 You are forbidden from assisting your users by providing tools for your users to remove, hide or obscure any indication of the software when you use the software to build your online service. - -5. Publish or integrate the software without modification - -5.1 You are authorized to publish the software on your personal sites, corporate official website or other third-party sites. -5.2 You are authorized to integrate the software with other systems, such as cloud virtual machine images, operating system images and so on. -5.3 Do not modify the source code of the software when you publish or integrate it. -5.4 All indications of the software must be kept the same when you publish or integrate the software. - -6. Publish derived work based on the software - -6.1 You are authorized to develop derived work based on the software. -6.2 The modified codes of the software in your derived work must follow the following terms: - - 6.2.1 The source codes must be released if you make any modification to the software. - 6.2.2 All indications of the software must be kept the same. - 6.2.3 You are entitled to add your indications to the modified codes. - 6.2.4 You are entitled to charge fees for the derived work you developed based on the software. - 6.2.5 You agree to authorize third party users to modify and release the derived work in compliance with 6.2. - -6.3 If the codes of the work are independently developed by yourself, You are authorized to release the work in either source code form or binary. You are entitled to charge your users or make it free. -6.4 None of the indications of the software can be removed, hidden or obscured in any way in the derived work you developed. - -7. Publish applications based on API of the software - -7.1 You are authorized to develop your applications based on the API of the software, for example, client software. -7.2 You are authorized to publish applications you developed based on the API in either source code form or binary. -7.3 You are authorized to use your own license to release applications you developed based on the API. -7.4 You are entitled to release applications you developed based on the API either free or with a charge. - -8. Exceptions - -If the terms above do not meet your requirements when using the software, please contact me for a more flexible license. - -9. Termination - -9.1 Violation of any of the terms of the agreement will result in immediate termination of this license. I reserve all rights to take legal actions in case of dispute. diff --git a/doc/LICENSE.CN b/doc/LICENSE.CN new file mode 100644 index 0000000000..8baab2b794 --- /dev/null +++ b/doc/LICENSE.CN @@ -0,0 +1,102 @@ +Z PUBLIC LICENSE 1.2 + +许可 + +Z PUBLIC LICENSE 由青岛易软天创网络科技有限公司(www.cnezsoft.com)起草,简称ZPL协议。 +任何人均可使用该协议来发布开源软件,并可对下面协议正文中以下划线标注的空白部分做相应修改, +除此之外的任何内容不得做任何修改。青岛易软天创网络科技有限公司拥有对该协议条款的最终解释权。 + +前言: + +禅道项目管理软件(以下简称该软件)由 青岛易软天创网络科技有限公司(www.cnezsoft.com)开发(以下简称我)。我依法拥有该软件的所有版权。 +本着共享开放的角度,我以开放源代码的形式发布该软件。您可以在遵守该协议的前提下使用该软件。 +自您安装该软件开始,您和我之间的合同关系自动成立。除非您停止使用该软件或与我有签署额外合同, +您须认真遵循该授权协议约定的每一条款。 + +我的联系方式: +联系人:徐先生 +电话: 4006-8899-23 +Email: co@cnezsoft.com +QQ: 1492153927 +地址: 青岛开发区武夷山路167号千禧龙花园 9-1-101室 + +约定: + +下述条款中所指该软件的标志包括如下方面: + + 该软件源代码及文档中关于该软件的版权提示、文字、图片和链接。 + 该软件运行时界面上呈现出来的有关该软件的文字、图片和链接。 + +不包括如下方面: + + 该软件提供的演示数据中关于该软件的文字、图片和链接。 + +一、免责 + +该软件是以开放源代码的方式发行,您使用该软件无需任何费用,因此在使用该软件前,您须知晓: + +1.1 我没有对该软件提供任何技术支持的义务,您可联系我购买商业的技术支持。 +1.2 我对因使用该软件而产生直接或间接的任何问题不负任何责任。 +1.3 开源不等于免费,开源不等于无版权,开源软件的发展需要您我共同的努力。 + +二、自用该软件 + +2.1 您个人或您就职的公司(组织)可自由使用该软件,我不对您或您就职公司(组织)的性质做任何限制。 +2.2 您可以在您个人或您就职公司(组织)任意数量的电脑上运行该软件,我不对电脑的数量做任何限制。 +2.3 您可以对该软件源代码进行修改以适应您个人或您所在公司(组织)使用的要求,您做的改动无需对外发布。 +2.4 您个人或您就职公司(组织)使用该软件时,必须保留该软件的所有标志,不得以任何方式隐藏或遮掩任一标志。 + +三、为用户定制 + +3.1 您可以使用该软件为您的用户部署各种形式的应用,我不对应用的性质做任何限制。 +3.2 您可以使用该软件为您的用户部署任意数量的应用,我不对应用的数量做任何限制。 +3.3 您可以对该软件源代码进行修改以适应您的用户的要求,您做的改动无需对外发布。 +3.4 您对该软件源代码所做的修改可以源代码或二进制的方式提供给您的用户。 +3.5 您使用该软件为您的任一用户部署的任一应用都必须保留该软件所有的标志。 +3.6 您使用该软件为您的任一用户部署的任一应用都不得以任何方式隐藏或遮掩该软件任一标志。 + +四、提供在线服务 + +4.1 您可以使用该软件搭建在线服务,为您的用户提供服务,我不对该服务及该服务用户的性质做任何限制。 +4.2 您可以使用该软件搭建在线服务,为您的用户提供服务,我不对该服务的用户数量做任何限制。 +4.3 您可以对该软件源代码进行修改以适应在线服务的要求,您做的改动无需对外发布。 +4.4 您使用该软件搭建在线服务时,必须以明确的方式告知您的用户该服务是基于该软件搭建的。 +4.5 您使用该软件搭建在线服务为您的任一用户部署的任一应用必须保留该软件所有的标志。 +4.6 您使用该软件搭建在线服务为您的任一用户部署的任一应用不得以任何方式隐藏或遮掩该软件任一标志。 +4.7 您使用该软件搭建在线服务时,不得为您的用户提供去除、隐藏或遮掩该软件任一标志的功能。 + +五、无改动发布或集成该软件 + +5.1 我欢迎并感谢您将该软件发布在您的个人网站、企业官网或者其他的第三方网站。 +5.2 我欢迎并感谢您将该软件集成在其他系统中一起发布,比如云服务镜像、操作系统发行版等。 +5.3 您在发布或者集成该软件的时候,不得对该软件源码做任何改动。 +5.4 您在发布或者集成该软件的时候,须保留该软件的所有标志。 + +六、发布基于该软件的衍生作品 + +6.1 我欢迎并感谢您为该软件开发衍生作品。 +6.2 您开发的衍生作品中涉及到对该软件源代码改动的地方,须遵循如下条款: + + 6.2.1 如修改了该软件的源代码,须依据本协议发布修改后的源代码。 + 6.2.2 如修改了该软件的源代码,须保留代码里面该软件原有的所有标志。 + 6.2.3 您可以在代码中追加您自己的标志。 + 6.2.4 您可以对您开发的衍生作品进行收费。 + 6.2.5 第三方的用户可在遵循6.2所有条款下可继续在您开发的衍生作品基础上进行修改并发布。 + +6.3 您开发的衍生作品中独立于本软件开发的代码,可以源代码或二进制的方式进行发布,可免费或收费发布。 +6.4 您开发的衍生作品不得以任何方式去除、隐藏或遮掩该软件的任一标志。 + +七、发布基于该软件API的应用 + +7.1 我欢迎并感谢您为该软件开发基于API的各种应用,比如客户端软件等。 +7.2 您基于该软件API机制开发的应用,可以源代码或者二进制的方式进行发布,我对此没有任何限制。 +7.3 您基于该软件API机制开发的应用,授权协议可以自行约定,我对此没有任何限制。 +7.4 您基于该软件API机制开发的应用,可以免费或者收费发布,我对此没有任何限制。 + +八、授权例外 + +如果上述条款无法满足您使用该软件的要求,可联系我签署额外的合同以获得更灵活的授权许可。 + +九、合同约束 + +9.1 如果您违反了该协议的任一条款,该授权协议将自动终止,我保留通过法律手段追究责任的权利。 diff --git a/doc/LICENSE.EN b/doc/LICENSE.EN new file mode 100644 index 0000000000..16cc3a8dce --- /dev/null +++ b/doc/LICENSE.EN @@ -0,0 +1,99 @@ +Z PUBLIC LICENSE 1.2 + +Authorization + +Z PUBLIC LICENSE, also known as ZPL Agreement, is drafted by QingDao Nature Easy Soft Network Technology Co,LTD. (,www.cnezsoft.com). +Anyone can use the agreement to publish open source software, and modify the blank underlined part of the following text of the agreement accordingly. +No other text of the agreement shall be changed. QingDao Nature Easy Soft Network Technology Co,LTD has the final authority to interpret the terms of the agreement. + +Preface + +ZenTaoPMS (Hereinafter referred to as "the software") developed by Nature EasySoft Network Tecnology Co.ltd, QingDao, China (www.cnezsoft.com) (hereinafter referred to I). I'm entitled to all copyright of the software. +The software is released as open source software. You are authorized to use the software as long as you are in compliance with this agreement. +By installation of the software, you agree that a contractual relationship between you and me is automatically established. +You are obliged to fully comply with all the terms of this agreement unless you choose to stop using the software or you have signed additional contracts with me. + +My Contact: +Email: co@easysoft.ltd +Site: http://www.zentao.pm + +We agree: + +Indications of the software include: + + Notes, texts, pictures and links showing copyright attribution of the software in the source code and related documentation. + and texts, picture and links on the interface of the software when running. + +Excluding + + texts, picture and links on the interface of the demo versions of the software. + +1. Disclaimer + +The software is an open-source software, so you are authorized to use the software without paying a fee. Before you start to use it, please note: + +1.1 I do not have any obligation to provide technical support for the software. You can contact me to purchase technical support service. +1.2 I'm not responsible for any liability caused by your using the software directly or indirectly. +1.3 Open source software does not mean it's free of charge, neither does it mean the software does not enjoy copyright. + +2. For personal use + +2.1 You or your company/organization are authorized to use the software for your internal use for both commercial and non-commercial purposes.. +2.2 You or your company/organization are authorized to run the software on any number of computers. +2.3 You or your company/organization are authorized to modify the source code of the software to meet your requirements. You do not need to release the modified codes. +2.4 You or your company/organization must keep all the indications of the software when using it. None of the indications can be removed, hidden or obscured in any way. + +3. For customized software + +3.1 You are authorized to use the software to deploy various forms of application for your users in any way you like. +3.2 You are authorized to use the software to deploy any number of applications for your users. +3.3 You are authorized to modify the source code to meet your user's requirements without releasing the modified codes. +3.4 You are authorized to provide the modified codes to your users in either source code form or binary. +3.5 You must keep all the indications of the software when providing applications to your users. +3.6 None of the indications of the software may be removed, hidden or obscured in any way when you provide applications to your users. + +4. Online service + +4.1 You are authorized to use the software to build your online service for your users in any way you like. +4.2 You are authorized to use the software to build your online service for any number of your users. +4.3 You are authorized to modify the source codes of the software to meet your user's requirements on online service without releasing the modified codes. +4.4 You must notify your users clearly that your service is based on the software when you use it to build your online service. +4.5 You must keep all the indications of the software when providing online service to your users. +4.6 You must keep all the indications of the software in any application you make for your users. None of the indications can be hidden or obscured in any way. +4.7 You are forbidden from assisting your users by providing tools for your users to remove, hide or obscure any indication of the software when you use the software to build your online service. + +5. Publish or integrate the software without modification + +5.1 You are authorized to publish the software on your personal sites, corporate official website or other third-party sites. +5.2 You are authorized to integrate the software with other systems, such as cloud virtual machine images, operating system images and so on. +5.3 Do not modify the source code of the software when you publish or integrate it. +5.4 All indications of the software must be kept the same when you publish or integrate the software. + +6. Publish derived work based on the software + +6.1 You are authorized to develop derived work based on the software. +6.2 The modified codes of the software in your derived work must follow the following terms: + + 6.2.1 The source codes must be released if you make any modification to the software. + 6.2.2 All indications of the software must be kept the same. + 6.2.3 You are entitled to add your indications to the modified codes. + 6.2.4 You are entitled to charge fees for the derived work you developed based on the software. + 6.2.5 You agree to authorize third party users to modify and release the derived work in compliance with 6.2. + +6.3 If the codes of the work are independently developed by yourself, You are authorized to release the work in either source code form or binary. You are entitled to charge your users or make it free. +6.4 None of the indications of the software can be removed, hidden or obscured in any way in the derived work you developed. + +7. Publish applications based on API of the software + +7.1 You are authorized to develop your applications based on the API of the software, for example, client software. +7.2 You are authorized to publish applications you developed based on the API in either source code form or binary. +7.3 You are authorized to use your own license to release applications you developed based on the API. +7.4 You are entitled to release applications you developed based on the API either free or with a charge. + +8. Exceptions + +If the terms above do not meet your requirements when using the software, please contact me for a more flexible license. + +9. Termination + +9.1 Violation of any of the terms of the agreement will result in immediate termination of this license. I reserve all rights to take legal actions in case of dispute. diff --git a/framework/base/router.class.php b/framework/base/router.class.php index d700da5fc4..fddd0fc42b 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -1485,8 +1485,8 @@ class baseRouter if(!method_exists($tmpModelClass, $method)) continue; $methodRelfection = new reflectionMethod($tmpModelClass, $method); $definedFile = $methodRelfection->getFileName(); - $startLine = $methodRelfection->getStartLine() . ' '; - $endLine = $methodRelfection->getEndLine() . ' '; + $startLine = $methodRelfection->getStartLine(); + $endLine = $methodRelfection->getEndLine(); /* 将Hook脚本和老的代码合并在一起,并替换原来的定义。Merge hook codes with old codes and replace back. */ $oldCodes = $definedFile == $tmpModelFile ? $mergedModelCodes : $mainModelCodes; @@ -2184,6 +2184,7 @@ class baseRouter { /* 设置错误信息(Set the error info) */ $message = htmlspecialchars($message); + if(preg_match('/[^\x00-\x80]/', $message)) $message = helper::convertEncoding($message, 'gbk'); $log = "ERROR: $message in $file on line $line"; if(isset($_SERVER['SCRIPT_URI'])) $log .= ", request: $_SERVER[SCRIPT_URI]";; $trace = debug_backtrace(); @@ -2236,6 +2237,7 @@ class baseRouter * 设置错误信息。 * Set the error info. **/ + if(preg_match('/[^\x00-\x80]/', $message)) $message = helper::convertEncoding($message, 'gbk'); $errorLog = "\n" . date('H:i:s') . " $message in $file on line $line "; $errorLog .= "when visiting " . htmlspecialchars($this->getURI()) . "\n"; diff --git a/framework/helper.class.php b/framework/helper.class.php index 39a7629714..e54e60d459 100644 --- a/framework/helper.class.php +++ b/framework/helper.class.php @@ -5,7 +5,7 @@ * * The author disclaims copyright to this source code. In place of * a legal notice, here is a blessing: - * + * * May you do good and not evil. * May you find forgiveness for yourself and forgive others. * May you share freely, never taking more than you give. @@ -43,7 +43,7 @@ class helper extends baseHelper { if(isset($_GET[$config->viewVar])) { - $viewType = $_GET[$config->viewVar]; + $viewType = $_GET[$config->viewVar]; } else { @@ -59,9 +59,9 @@ class helper extends baseHelper /** * Encode json for $.parseJSON - * - * @param array $data - * @param int $options + * + * @param array $data + * @param int $options * @static * @access public * @return string @@ -78,10 +78,10 @@ class helper extends baseHelper /** * Convert encoding. - * - * @param string $string - * @param string $fromEncoding - * @param string $toEncoding + * + * @param string $string + * @param string $fromEncoding + * @param string $toEncoding * @static * @access public * @return string @@ -111,12 +111,33 @@ class helper extends baseHelper return $string; } + + /** + * Calculate two working days. + * + * @param string $begin + * @param string $end + * + * @return bool|float + */ + static public function workDays($begin, $end) + { + $begin = strtotime($begin); + $end = strtotime($end); + if($end < $begin) return false; + + $double = floor(($end - $begin) / (7 * 24 * 3600)); + $begin = date('w', $begin); + $end = date('w', $end); + $end = $begin > $end ? $end + 5 : $end; + return $double * 5 + $end - $begin; + } } /** * 检查是否是onlybody模式。 * Check exist onlybody param. - * + * * @access public * @return void */ @@ -140,4 +161,4 @@ function formatTime($time, $format = '') if(trim($time) == '') return ; if($format) return date($format, strtotime($time)); return trim($time); -} \ No newline at end of file +} diff --git a/lib/base/dao/dao.class.php b/lib/base/dao/dao.class.php index de4318b9f7..cffee28715 100644 --- a/lib/base/dao/dao.class.php +++ b/lib/base/dao/dao.class.php @@ -1356,6 +1356,10 @@ class baseDAO { $field['rule'] = 'date'; } + elseif($type == 'datetime') + { + $field['rule'] = 'datetime'; + } else { $field['rule'] = 'skip'; @@ -1993,11 +1997,16 @@ class baseSQL $pos = stripos($order, 'limit'); $orders = $pos ? substr($order, 0, $pos) : $order; $limit = $pos ? substr($order, $pos) : ''; - if($limit and !preg_match('/^[0-9]+ *(, *[0-9]+)?$/', $limit)) $limit = ''; + if(!empty($limit)) + { + $trimedLimit = trim(str_replace('limit', '', $limit)); + if(!preg_match('/^[0-9]+ *(, *[0-9]+)?$/', $trimedLimit)) die("Limit is bad query, The limit is " . htmlspecialchars($limit)); + } + $orders = trim($orders); if(empty($orders)) return $this; - if(!preg_match('/^(\w+\.)?(`\w+`|\w+)( +(desc|asc))?( *(, *(\w+\.)?(`\w+`|\w+)( +(desc|asc))?)?)*$/i', $orders)) die("Order is bad request, The order is $orders"); + if(!preg_match('/^(\w+\.)?(`\w+`|\w+)( +(desc|asc))?( *(, *(\w+\.)?(`\w+`|\w+)( +(desc|asc))?)?)*$/i', $orders)) die("Order is bad request, The order is " . htmlspecialchars($orders)); $orders = explode(',', $orders); foreach($orders as $i => $order) diff --git a/lib/base/filter/filter.class.php b/lib/base/filter/filter.class.php index a4491fc604..ceaacadb8b 100644 --- a/lib/base/filter/filter.class.php +++ b/lib/base/filter/filter.class.php @@ -262,12 +262,31 @@ class baseValidater */ public static function checkDate($date) { + if(empty($date)) return true; if($date == '0000-00-00') return true; $stamp = strtotime($date); if(!is_numeric($stamp)) return false; return checkdate(date('m', $stamp), date('d', $stamp), date('Y', $stamp)); } + /** + * Check datetime. + * + * @param string $datetime + * @static + * @access public + * @return bool + */ + public static function checkDatetime($datetime) + { + if(empty($datetime)) return true; + if($datetime == '0000-00-00') return true; + if($datetime == '0000-00-00 00:00:00') return true; + $stamp = strtotime($datetime); + if(!is_numeric($stamp)) return false; + return checkdate(date('m', $stamp), date('d', $stamp), date('Y', $stamp)); + } + /** * 检查正则表达式。 * REG checking. diff --git a/lib/dao/dao.class.php b/lib/dao/dao.class.php index ea12a7ddb6..441109e7b3 100644 --- a/lib/dao/dao.class.php +++ b/lib/dao/dao.class.php @@ -22,7 +22,7 @@ class dao extends baseDAO { public function exec($sql = '') { - if(isset($_SESSION['tutorialMode']) and $_SESSION['tutorialMode']) die(js::alert($this->lang->error->tutorialData)); + if(isset($_SESSION['tutorialMode']) and $_SESSION['tutorialMode']) die(); return parent::exec($sql); } diff --git a/lib/front/front.class.php b/lib/front/front.class.php index 8c6a881a13..99dedc8632 100644 --- a/lib/front/front.class.php +++ b/lib/front/front.class.php @@ -124,6 +124,24 @@ class html extends baseHTML /* End. */ return $string .= "\n"; } + + /** + * Create input tag that type is number. + * + * @param string $name + * @param string $value + * @param string $attrib + * @static + * @access public + * @return string + */ + static public function number($name, $value = '', $attrib = '') + { + $id = "id='$name'"; + if(strpos($attrib, 'id=') !== false) $id = ''; + $value = str_replace("'", ''', $value); + return "\n"; + } } /** diff --git a/lib/pager/pager.class.php b/lib/pager/pager.class.php index b315d1e949..6431fd349f 100644 --- a/lib/pager/pager.class.php +++ b/lib/pager/pager.class.php @@ -20,4 +20,30 @@ helper::import(dirname(dirname(__FILE__)) . '/base/pager/pager.class.php'); */ class pager extends basePager { + /** + * Show pager. + * + * @param string $align + * @param string $type + * @access public + * @return void + */ + public function show($align = 'right', $type = 'full') + { + if($type == 'pagerjs') + { + $this->setParams(); + $params = $this->params; + foreach($params as $key => $value) + { + if(strtolower($key) == 'recperpage') $params[$key] = '{recPerPage}'; + if(strtolower($key) == 'pageid') $params[$key] = '{page}'; + } + echo ""; + } + else + { + parent::show($align, $type); + } + } } diff --git a/module/action/control.php b/module/action/control.php index 5916f33db9..be3f932140 100755 --- a/module/action/control.php +++ b/module/action/control.php @@ -115,9 +115,6 @@ class action extends control public function comment($objectType, $objectID) { $actionID = $this->action->create($objectType, $objectID, 'Commented', $this->post->comment); - - $moduleName = $objectType == 'case' ? 'testcase' : $objectType; - $this->loadModel($moduleName)->sendmail($objectID, $actionID); die(js::reload('parent')); } diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 34e6c6c784..6a988dc0a6 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -12,10 +12,10 @@ $lang->action->common = 'Log'; $lang->action->product = $lang->productCommon; $lang->action->project = $lang->projectCommon; -$lang->action->objectType = 'Object'; +$lang->action->objectType = 'Object Type'; $lang->action->objectID = 'ID'; -$lang->action->objectName = 'Name'; -$lang->action->actor = 'Done by'; +$lang->action->objectName = 'Object Name'; +$lang->action->actor = 'Operator'; $lang->action->action = 'Action'; $lang->action->actionID = 'Action ID'; $lang->action->date = 'Date'; @@ -27,7 +27,7 @@ $lang->action->hideAll = 'Hide All'; $lang->action->editComment = 'Edit'; $lang->action->comment = 'Comment'; -$lang->action->trashTips = 'Note: Delete in ZenTao is logic.'; +$lang->action->trashTips = 'Note: All Deletion in ZenTao are logical.'; $lang->action->textDiff = 'Text Format'; $lang->action->original = 'Original Format'; $lang->action->confirmHideAll = 'Do you want to hide all the records?'; @@ -44,11 +44,11 @@ $lang->action->history->diff = 'Diff'; $lang->action->dynamic = new stdclass(); $lang->action->dynamic->today = 'Today'; $lang->action->dynamic->yesterday = 'Yesterday'; -$lang->action->dynamic->twoDaysAgo = 'Two Days Ago'; -$lang->action->dynamic->thisWeek = 'This Week'; -$lang->action->dynamic->lastWeek = 'Last Week'; -$lang->action->dynamic->thisMonth = 'This Month'; -$lang->action->dynamic->lastMonth = 'Last Month'; +$lang->action->dynamic->twoDaysAgo = 'TwoDaysAgo'; +$lang->action->dynamic->thisWeek = 'ThisWeek'; +$lang->action->dynamic->lastWeek = 'LastWeek'; +$lang->action->dynamic->thisMonth = 'ThisMonth'; +$lang->action->dynamic->lastMonth = 'LastMonth'; $lang->action->dynamic->all = 'All'; $lang->action->dynamic->hidden = 'Hidden'; $lang->action->dynamic->search = 'Search'; @@ -68,7 +68,7 @@ $lang->action->objectTypes['testtask'] = 'Test Build'; $lang->action->objectTypes['user'] = 'User'; $lang->action->objectTypes['doc'] = 'Doc'; $lang->action->objectTypes['doclib'] = 'Doc Lib'; -$lang->action->objectTypes['todo'] = 'To-Dos'; +$lang->action->objectTypes['todo'] = 'Todo'; $lang->action->objectTypes['branch'] = 'Branch'; $lang->action->objectTypes['module'] = 'Module'; $lang->action->objectTypes['testsuite'] = 'Suite'; @@ -143,7 +143,7 @@ $lang->action->label->blocked = 'Blocked'; $lang->action->label->resolved = 'Resolved'; $lang->action->label->reviewed = 'Reviewed'; $lang->action->label->moved = 'Moved'; -$lang->action->label->confirmed = 'Confirm a Story, '; +$lang->action->label->confirmed = 'Confirm a Story'; $lang->action->label->bugconfirmed = 'Confirmed'; $lang->action->label->tostory = 'Convert to Story'; $lang->action->label->frombug = 'Converted from Bug'; @@ -197,7 +197,7 @@ $lang->action->label->case = 'Case|testcase|view|caseID=%s'; $lang->action->label->testtask = 'Test Task|testtask|view|caseID=%s'; $lang->action->label->testsuite = 'Test Suite|testsuite|view|suiteID=%s'; $lang->action->label->caselib = 'Case Library|testsuite|libview|libID=%s'; -$lang->action->label->todo = 'To-Do|todo|view|todoID=%s'; +$lang->action->label->todo = 'Todo|todo|view|todoID=%s'; $lang->action->label->doclib = 'Doc Lib|doc|browse|libID=%s'; $lang->action->label->doc = 'Doc|doc|view|docID=%s'; $lang->action->label->user = 'User|user|view|account=%s'; @@ -220,7 +220,7 @@ $lang->action->search->objectTypeList['testtask'] = 'Test Task'; $lang->action->search->objectTypeList['user'] = 'User'; $lang->action->search->objectTypeList['doc'] = 'Doc'; $lang->action->search->objectTypeList['doclib'] = 'Doc Lib'; -$lang->action->search->objectTypeList['todo'] = 'To-Dos'; +$lang->action->search->objectTypeList['todo'] = 'Todo'; $lang->action->search->objectTypeList['build'] = 'Build'; $lang->action->search->objectTypeList['release'] = 'Release'; $lang->action->search->objectTypeList['productplan'] = 'Plan'; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index 7021b27d0d..0982cb1fee 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -191,13 +191,13 @@ $lang->action->label->release = '发布|release|view|productID=%s'; $lang->action->label->story = '需求|story|view|storyID=%s'; $lang->action->label->project = "{$lang->projectCommon}|project|view|projectID=%s"; $lang->action->label->task = '任务|task|view|taskID=%s'; -$lang->action->label->build = 'Build|build|view|buildID=%s'; +$lang->action->label->build = '版本|build|view|buildID=%s'; $lang->action->label->bug = 'Bug|bug|view|bugID=%s'; $lang->action->label->case = '用例|testcase|view|caseID=%s'; $lang->action->label->testtask = '测试单|testtask|view|caseID=%s'; $lang->action->label->testsuite = '测试套件|testsuite|view|suiteID=%s'; $lang->action->label->caselib = '测试库|testsuite|libview|libID=%s'; -$lang->action->label->todo = 'todo|todo|view|todoID=%s'; +$lang->action->label->todo = '待办|todo|view|todoID=%s'; $lang->action->label->doclib = '文档库|doc|browse|libID=%s'; $lang->action->label->doc = '文档|doc|view|docID=%s'; $lang->action->label->user = '用户|user|view|account=%s'; diff --git a/module/action/lang/zh-tw.php b/module/action/lang/zh-tw.php index 673315df31..638d10c6ee 100755 --- a/module/action/lang/zh-tw.php +++ b/module/action/lang/zh-tw.php @@ -25,6 +25,7 @@ $lang->action->undelete = '還原'; $lang->action->hideOne = '隱藏'; $lang->action->hideAll = '全部隱藏'; $lang->action->editComment = '修改備註'; +$lang->action->comment = '備註'; $lang->action->trashTips = '提示:為了保證系統的完整性,禪道系統的刪除都是標記刪除。'; $lang->action->textDiff = '文本格式'; @@ -190,13 +191,13 @@ $lang->action->label->release = '發佈|release|view|productID=%s'; $lang->action->label->story = '需求|story|view|storyID=%s'; $lang->action->label->project = "{$lang->projectCommon}|project|view|projectID=%s"; $lang->action->label->task = '任務|task|view|taskID=%s'; -$lang->action->label->build = 'Build|build|view|buildID=%s'; +$lang->action->label->build = '版本|build|view|buildID=%s'; $lang->action->label->bug = 'Bug|bug|view|bugID=%s'; $lang->action->label->case = '用例|testcase|view|caseID=%s'; $lang->action->label->testtask = '測試單|testtask|view|caseID=%s'; $lang->action->label->testsuite = '測試套件|testsuite|view|suiteID=%s'; $lang->action->label->caselib = '測試庫|testsuite|libview|libID=%s'; -$lang->action->label->todo = 'todo|todo|view|todoID=%s'; +$lang->action->label->todo = '待辦|todo|view|todoID=%s'; $lang->action->label->doclib = '文檔庫|doc|browse|libID=%s'; $lang->action->label->doc = '文檔|doc|view|docID=%s'; $lang->action->label->user = '用戶|user|view|account=%s'; diff --git a/module/action/model.php b/module/action/model.php index 1907cb753d..4aff2f30df 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -61,7 +61,7 @@ class actionModel extends model $this->file->updateObjectID($this->post->uid, $objectID, $objectType); - $this->loadModel('webhook')->send($objectType, $objectID, $actionType, $actionID); + $this->loadModel('message')->send($objectType, $objectID, $actionType, $actionID); return $actionID; } @@ -325,6 +325,22 @@ class actionModel extends model } } } + elseif($actionName == 'finished' and $objectType == 'todo') + { + $action->appendLink = ''; + if(strpos($action->extra, ':')!== false) + { + list($extra, $id) = explode(':', $action->extra); + $action->extra = strtolower($extra); + if($id) + { + $table = $this->config->objectTables[$action->extra]; + $field = $this->config->action->objectNameFields[$action->extra]; + $name = $this->dao->select($field)->from($table)->where('id')->eq($id)->fetch($field); + if($name) $action->appendLink = html::a(helper::createLink($action->extra, 'view', "id=$id"), "#$id " . $name); + } + } + } $action->history = isset($histories[$actionID]) ? $histories[$actionID] : array(); $actionName = strtolower($action->action); @@ -691,7 +707,7 @@ class actionModel extends model $objectIds = array_unique($objectIds); $table = $this->config->objectTables[$objectType]; $field = $this->config->action->objectNameFields[$objectType]; - if($table != '`zt_todo`') + if($table != TABLE_TODO) { $objectNames[$objectType] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->fetchPairs(); } diff --git a/module/action/view/trash.html.php b/module/action/view/trash.html.php index a4f9a569c5..b09a3818d8 100755 --- a/module/action/view/trash.html.php +++ b/module/action/view/trash.html.php @@ -23,7 +23,7 @@ recTotal}&recPerPage={$pager->recPerPage}"; ?> - action->objectType);?> + action->objectType);?> idAB);?> action->objectName;?> action->actor);?> diff --git a/module/admin/control.php b/module/admin/control.php index c4a23b65ec..db0f309c6a 100644 --- a/module/admin/control.php +++ b/module/admin/control.php @@ -331,6 +331,9 @@ class admin extends control $this->send(array('result' => 'success', 'message' => $this->lang->admin->saveSuccess, 'locate' => 'reload')); } + $this->loadModel('message'); + $this->loadModel('webhook'); + $this->view->title = $this->lang->admin->log; $this->view->position[] = html::a($this->createLink('webhook', 'browse'), $this->lang->admin->api); $this->view->position[] = $this->lang->admin->log; diff --git a/module/admin/lang/en.php b/module/admin/lang/en.php index f7c4e122d0..643e542eff 100644 --- a/module/admin/lang/en.php +++ b/module/admin/lang/en.php @@ -29,23 +29,23 @@ $lang->admin->saveSuccess = 'Saved.'; $lang->admin->info = new stdclass(); $lang->admin->info->version = 'Current Version is %s. '; -$lang->admin->info->links = 'You can visit '; +$lang->admin->info->links = 'You can visit links below'; $lang->admin->info->account = 'Your ZenTao account is %s.'; $lang->admin->info->log = 'Logs that is beyond valid days will be deleted and it has to run cron.'; $lang->admin->notice = new stdclass(); -$lang->admin->notice->register = "Note: You haven't registered in ZenTao(www.zentao.pm). Register %s and get the latest ZenTao news."; +$lang->admin->notice->register = "Note: You haven't registered in ZenTao(www.zentao.pm). %s then get the Latest ZenTao Upgrades and News."; $lang->admin->notice->ignore = "Ignore"; $lang->admin->notice->int = "『%s』should be a positive integer."; $lang->admin->register = new stdclass(); -$lang->admin->register->common = 'Account Binding'; -$lang->admin->register->caption = 'Register'; -$lang->admin->register->click = 'Click Here'; -$lang->admin->register->lblAccount = 'at least 3 characters; must contain letters and numbers.'; -$lang->admin->register->lblPasswd = 'at least 6 characters; must contain letters and numbers.'; +$lang->admin->register->common = 'Binding New Account'; +$lang->admin->register->caption = 'Register in Zentao Community'; +$lang->admin->register->click = 'Please Register here'; +$lang->admin->register->lblAccount = 'at least 3 characters pls; contains letters and numbers.'; +$lang->admin->register->lblPasswd = 'at least 6 characters pls; contains letters and numbers.'; $lang->admin->register->submit = 'Register'; -$lang->admin->register->bind = "If you have already registered an account, link your account %s."; +$lang->admin->register->bind = "Binding Exsit Account"; $lang->admin->register->success = "You have registered with us!"; $lang->admin->bind = new stdclass(); @@ -54,20 +54,20 @@ $lang->admin->bind->success = "Account has been linked!"; $lang->admin->safe = new stdclass(); $lang->admin->safe->common = 'Security Policy'; -$lang->admin->safe->set = 'Password Security Settings'; -$lang->admin->safe->password = 'Password Security'; -$lang->admin->safe->weak = 'Weak Password'; +$lang->admin->safe->set = 'PasswordStrength'; +$lang->admin->safe->password = 'Password Strength'; +$lang->admin->safe->weak = 'Weak Passwords'; $lang->admin->safe->reason = 'Type'; -$lang->admin->safe->checkWeak = 'Weak Password Check'; -$lang->admin->safe->changeWeak = 'Change weak password'; +$lang->admin->safe->checkWeak = 'WeakPasswords'; +$lang->admin->safe->changeWeak = 'Weak password must be strengthen'; $lang->admin->safe->modifyPasswordFirstLogin = 'Change password when first login'; $lang->admin->safe->modeList[0] = 'N/A'; $lang->admin->safe->modeList[1] = 'Medium'; $lang->admin->safe->modeList[2] = 'Strong'; -$lang->admin->safe->modeRuleList[1] = 'must contain letters and numbers, at least six characters.'; -$lang->admin->safe->modeRuleList[2] = 'must contain letters, numbers and special characters, at least 10 characters.'; +$lang->admin->safe->modeRuleList[1] = 'Contains upper and lower case, numbers. Length >= 6'; +$lang->admin->safe->modeRuleList[2] = 'Contains upper and lower case, numbers and special characters. Length >= 10.'; $lang->admin->safe->reasonList['weak'] = 'Common Weak Password'; $lang->admin->safe->reasonList['account'] = 'Same as your account'; @@ -78,5 +78,5 @@ $lang->admin->safe->reasonList['birthday'] = 'Same as your DOB'; $lang->admin->safe->modifyPasswordList[1] = 'Yes'; $lang->admin->safe->modifyPasswordList[0] = 'No'; -$lang->admin->safe->noticeMode = 'User password will be checked when login, add/edit user password.'; -$lang->admin->safe->noticeStrong = 'The more uppercase letters and numbers a password has, the more secure it is!'; +$lang->admin->safe->noticeMode = 'Password will be checked when login, add/edit user.'; +$lang->admin->safe->noticeStrong = ''; diff --git a/module/admin/view/log.html.php b/module/admin/view/log.html.php index 0e14808819..58573316b4 100644 --- a/module/admin/view/log.html.php +++ b/module/admin/view/log.html.php @@ -10,16 +10,9 @@ * @link http://www.zentao.net */ ?> - +app->getModuleRoot() . 'webhook/view/header.html.php';?>
-
-
- createLink('webhook', 'browse'), $lang->admin->api);?> - admin->log;?> - admin->setting;?> -
-
diff --git a/module/backup/lang/en.php b/module/backup/lang/en.php index f197def427..d3df0e55ca 100644 --- a/module/backup/lang/en.php +++ b/module/backup/lang/en.php @@ -5,18 +5,18 @@ $lang->backup->history = 'History'; $lang->backup->delete = 'Delete'; $lang->backup->backup = 'Backup'; $lang->backup->restore = 'Restore'; -$lang->backup->change = 'Save Interval'; +$lang->backup->change = 'Modify days'; $lang->backup->changeAB = 'Modify'; -$lang->backup->time = 'Time'; +$lang->backup->time = 'Backup Time'; $lang->backup->files = 'Files'; $lang->backup->size = 'Size'; -$lang->backup->waitting = 'In Progree. Please wait...'; +$lang->backup->waitting = ' In Progress. Please wait...'; $lang->backup->confirmDelete = 'Do you want to delete the backup?'; $lang->backup->confirmRestore = 'Do you want to restore the backup?'; -$lang->backup->holdDays = 'Backup the latest %s days.'; -$lang->backup->restoreTip = 'Only files and databases will be restored when you click Restore. If you want to restore the code, restore it manually.'; +$lang->backup->holdDays = 'Reserve latest %s days of backups'; +$lang->backup->restoreTip = 'Only files and databases can be restored when you click Restore. Code can be restored manually.'; $lang->backup->success = new stdclass(); $lang->backup->success->backup = 'Done!'; diff --git a/module/backup/view/index.html.php b/module/backup/view/index.html.php index 14b9f79c9e..6ab73fe450 100644 --- a/module/backup/view/index.html.php +++ b/module/backup/view/index.html.php @@ -33,7 +33,7 @@ - + diff --git a/module/block/config.php b/module/block/config.php index 16b7ffefad..4d42c10ddc 100644 --- a/module/block/config.php +++ b/module/block/config.php @@ -12,10 +12,3 @@ $config->block = new stdclass(); $config->block->editor = new stdclass(); $config->block->editor->set = array('id' => 'html', 'tools' => 'simple'); - -$config->block->gridOptions[6] = '1/2'; -$config->block->gridOptions[4] = '1/3'; -$config->block->gridOptions[8] = '2/3'; -$config->block->gridOptions[3] = '1/4'; -$config->block->gridOptions[9] = '3/4'; -$config->block->gridOptions[12] = '100%'; diff --git a/module/block/control.php b/module/block/control.php index f41958fba4..805faf2520 100644 --- a/module/block/control.php +++ b/module/block/control.php @@ -54,9 +54,11 @@ class block extends control if($this->config->global->flow == 'onlyStory' or $this->config->global->flow == 'onlyTest') unset($modules['project']); $closedBlock = isset($this->config->block->closed) ? $this->config->block->closed : ''; - if(strpos(",$closedBlock,", ",|dynamic,") === false) $modules['dynamic'] = $this->lang->block->dynamic; + if(strpos(",$closedBlock,", ",|assigntome,") === false) $modules['assigntome'] = $this->lang->block->assignToMe; + if(strpos(",$closedBlock,", ",|dynamic,") === false) $modules['dynamic'] = $this->lang->block->dynamic; if(strpos(",$closedBlock,", ",|flowchart,") === false and $this->config->global->flow == 'full') $modules['flowchart'] = $this->lang->block->lblFlowchart; - if(strpos(",$closedBlock,", ",|html,") === false) $modules['html'] = 'HTML'; + if(strpos(",$closedBlock,", ",|welcome,") === false and $this->config->global->flow == 'full') $modules['welcome'] = $this->lang->block->welcome; + if(strpos(",$closedBlock,", ",|html,") === false) $modules['html'] = 'HTML'; $modules = array('' => '') + $modules; $hiddenBlocks = $this->block->getHiddenBlocks(); @@ -72,7 +74,6 @@ class block extends control $this->view->title = $title; $this->view->block = $this->block->getByID($id); $this->view->blockID = $id; - $this->view->title = $title; $this->display(); } @@ -103,6 +104,11 @@ class block extends control $params = $this->block->$func($source); $this->view->params = json_decode($params, true); } + elseif($type == 'assigntome') + { + $params = $this->block->getAssignToMeParams(); + $this->view->params = json_decode($params, true); + } $this->view->source = $source; $this->view->type = $type; @@ -209,6 +215,7 @@ class block extends control if($this->block->initBlock($module)) die(js::reload()); } + $shortBlocks = $longBlocks = array(); foreach($blocks as $key => $block) { if($this->config->global->flow == 'onlyStory' and $block->source != 'product' and $block->source != 'todo' and $block->block != 'dynamic') unset($blocks[$key]); @@ -230,15 +237,22 @@ class block extends control { $block->moreLink = $this->createLink('company', 'dynamic'); } + + if($this->block->isLongBlock($block)) + { + $longBlocks[$key] = $block; + } + else + { + $shortBlocks[$key] = $block; + } } - $this->view->blocks = $blocks; - $this->view->module = $module; + $this->view->longBlocks = $longBlocks; + $this->view->shortBlocks = $shortBlocks; + $this->view->module = $module; - if($this->app->getViewType() == 'json') - { - die(json_encode($blocks)); - } + if($this->app->getViewType() == 'json') die(json_encode($blocks)); $this->display(); } @@ -256,6 +270,39 @@ class block extends control $this->display(); } + /** + * Welcome block. + * + * @access public + * @return void + */ + public function welcome() + { + $projects = $this->loadModel('project')->getPairs(); + $products = $this->loadModel('product')->getPairs(); + + $this->view->tutorialed = $this->loadModel('tutorial')->getTutorialed(); + $this->view->tasks = (int)$this->dao->select('count(*) AS count')->from(TABLE_TASK)->where('assignedTo')->eq($this->app->user->account)->fetch('count'); + $this->view->bugs = (int)$this->dao->select('count(*) AS count')->from(TABLE_BUG)->where('assignedTo')->eq($this->app->user->account)->fetch('count'); + $this->view->stories = (int)$this->dao->select('count(*) AS count')->from(TABLE_STORY)->where('assignedTo')->eq($this->app->user->account)->fetch('count'); + $this->view->projects = (int)$this->dao->select('count(*) AS count')->from(TABLE_PROJECT)->where('id')->in(array_keys($projects))->andWhere("(status='wait' or status='doing')")->fetch('count'); + $this->view->products = (int)$this->dao->select('count(*) AS count')->from(TABLE_PRODUCT)->where('status')->ne('closed')->andWhere('id')->in(array_keys($products))->fetch('count'); + + $today = date('Y-m-d'); + $this->view->delay['task'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_TASK)->where('assignedTo')->eq($this->app->user->account)->andWhere('deadline')->ne('0000-00-00')->andWhere('deadline')->lt($today)->fetch('count'); + $this->view->delay['bug'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_BUG)->where('assignedTo')->eq($this->app->user->account)->andWhere('deadline')->ne('0000-00-00')->andWhere('deadline')->lt($today)->fetch('count'); + $this->view->delay['project'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_PROJECT)->where('id')->in(array_keys($projects))->andWhere("(status='wait' or status='doing')")->andWhere('end')->lt($today)->fetch('count'); + + $time = date('H:i'); + $welcomeType = '19:00'; + foreach($this->lang->block->welcomeList as $type => $name) + { + if($time >= $type) $welcomeType = $type; + } + $this->view->welcomeType = $welcomeType; + $this->display(); + } + /** * Print block. * @@ -272,7 +319,7 @@ class block extends control $html = ''; if($block->block == 'html') { - $html = "
" . htmlspecialchars_decode($block->params->html) .'
'; + $html = "
" . htmlspecialchars_decode($block->params->html) .'
'; } elseif($block->source != '') { @@ -281,7 +328,7 @@ class block extends control $this->get->set('module', $block->module); $this->get->set('source', $block->source); $this->get->set('blockid', $block->block); - $this->get->set('param',base64_encode(json_encode($block->params))); + $this->get->set('param', base64_encode(json_encode($block->params))); $html = $this->fetch('block', 'main', "module={$block->source}&id=$id"); } elseif($block->block == 'dynamic') @@ -292,8 +339,17 @@ class block extends control { $html = $this->fetch('block', 'flowchart'); } + elseif($block->block == 'assigntome') + { + $this->get->set('param', base64_encode(json_encode($block->params))); + $html = $this->fetch('block', 'printAssignToMeBlock', 'longBlock=' . $this->block->isLongBlock($block)); + } + elseif($block->block == 'welcome') + { + $html = $this->fetch('block', 'welcome'); + } - die($html); + echo $html; } /** @@ -327,9 +383,11 @@ class block extends control $block = $this->block->getByID($id); - echo ""; - echo ''; - if(isset($block->source)) echo ""; + echo '
'; + echo ''; + echo '
'; + echo html::select('moduleBlock', $blockPairs, ($block and $block->source != '') ? $block->block : '', "class='form-control chosen'"); + echo '
'; } elseif($mode == 'getblockform') { @@ -358,6 +416,9 @@ class block extends control $this->view->sign = strpos($sso, '?') === false ? '?' : '&'; } + $block = $this->block->getByID($id); + $this->view->longBlock = $this->block->isLongBlock($block); + $this->viewType = (isset($params->viewType) and $params->viewType == 'json') ? 'json' : 'html'; $this->params = $params; $this->view->code = $this->get->blockid; @@ -611,7 +672,18 @@ class block extends control $num = isset($this->params->num) ? (int)$this->params->num : 0; $type = isset($this->params->type) ? $this->params->type : ''; $pager = pager::init(0, $num , 1); - $this->view->productStats = $this->loadModel('product')->getStats('order_desc', $this->viewType != 'json' ? $pager : '', $type); + + $productStats = $this->loadModel('product')->getStats('order_desc', $this->viewType != 'json' ? $pager : '', $type); + $productIdList = array(); + foreach($productStats as $product) $productIdList[] = $product->id; + + $this->view->projects = $this->dao->select('t1.product,t2.name')->from(TABLE_PROJECTPRODUCT)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id') + ->where('t1.product')->in($productIdList) + ->andWhere('t2.deleted')->eq(0) + ->orderBy('t1.project') + ->fetchPairs('product', 'name'); + $this->view->productStats = $productStats; } /** @@ -630,6 +702,75 @@ class block extends control $this->view->projectStats = $this->loadModel('project')->getProjectStats($type, $productID = 0, $branch = 0, $itemCounts = 30, $orderBy = 'order_desc', $this->viewType != 'json' ? $pager : ''); } + /** + * Print assign to me block. + * + * @access public + * @return void + */ + public function printAssignToMeBlock($longBlock = true) + { + if(common::hasPriv('todo', 'view')) $hasViewPriv['todo'] = true; + if(common::hasPriv('task', 'view')) $hasViewPriv['task'] = true; + if(common::hasPriv('bug', 'view')) $hasViewPriv['bug'] = true; + + $params = $this->get->param; + $params = json_decode(base64_decode($params)); + + if(isset($hasViewPriv['todo'])) + { + $this->app->loadClass('date'); + $this->app->loadLang('todo'); + $stmt = $this->dao->select('*')->from(TABLE_TODO) + ->where("(assignedTo = '{$this->app->user->account}' or (assignedTo = '' and account='{$this->app->user->account}'))") + ->andWhere('status')->ne('done') + ->andWhere('cycle')->eq(0) + ->orderBy('`date`'); + if(isset($params->todoNum)) $stmt->limit($params->todoNum); + $todos = $stmt->fetchAll(); + + foreach($todos as $todo) + { + $todo->begin = date::formatTime($todo->begin); + $todo->end = date::formatTime($todo->end); + } + if(empty($todos)) unset($hasViewPriv['todo']); + $this->view->todos = $todos; + } + if(isset($hasViewPriv['task'])) + { + $this->app->loadLang('task'); + $stmt = $this->dao->select('*')->from(TABLE_TASK) + ->where('assignedTo')->eq($this->app->user->account) + ->andWhere('deleted')->eq('0') + ->andWhere('status')->ne('closed') + ->orderBy('id_desc'); + if(isset($params->taskNum)) $stmt->limit($params->taskNum); + $tasks = $stmt->fetchAll(); + + if(empty($tasks)) unset($hasViewPriv['task']); + $this->view->tasks = $tasks; + } + if(isset($hasViewPriv['bug'])) + { + $this->app->loadLang('bug'); + $stmt = $this->dao->select('*')->from(TABLE_BUG) + ->where('assignedTo')->eq($this->app->user->account) + ->andWhere('deleted')->eq('0') + ->andWhere('status')->ne('closed') + ->orderBy('id_desc'); + if(isset($params->bugNum)) $stmt->limit($params->bugNum); + $bugs = $stmt->fetchAll(); + + if(empty($bugs)) unset($hasViewPriv['bug']); + $this->view->bugs = $bugs; + } + + $this->view->hasViewPriv = $hasViewPriv; + $this->view->longBlock = $longBlock; + $this->display(); + } + /** * Print flow chart block * @access public diff --git a/module/block/css/admin.css b/module/block/css/admin.css index 31ad83a92c..4da9ab98db 100644 --- a/module/block/css/admin.css +++ b/module/block/css/admin.css @@ -1,8 +1,3 @@ -.input-group-btn .dropdown-toggle {border-radius: 4px;} -.dropdown-menu {min-width: 120px;} -.dropdown-menu.colors {padding: 5px; width: 205px} -.dropdown-menu.buttons {padding: 5px; padding-bottom: 0; padding-right: 0;} -.dropdown-menu.buttons > li {margin-bottom: 5px; display: block; float: left; width: 33.333333%; padding-right: 5px} -.table.table-form{margin-bottom:0px;} -#blockParam{padding-right:100px;} -#blockParam .table td, #blockParam .table th{border-bottom:0px;} +#blockAdmin {min-height: 280px;} +#blockAdmin .form-actions {visibility: hidden;} +#blockAdmin.form-inited .form-actions {visibility: visible;} diff --git a/module/block/css/dashboard.css b/module/block/css/dashboard.css index e6a24741c1..e69de29bb2 100644 --- a/module/block/css/dashboard.css +++ b/module/block/css/dashboard.css @@ -1,90 +0,0 @@ -body {background: #fafafa;} - -.page-content {margin-top: -19px; border-top: 1px solid #3280fc;} - -.dashboard {position: relative;} -.dashboard .row {margin: 0 auto;} -.dashboard .panel-actions {margin-top: 0; margin-right: 0;} -.dashboard .panel-heading {line-height: 17px; height: 30px; position: relative;} -.dashboard .panel-actions {position: absolute; top: 0; right: 0; height: 30px;} -.dashboard .panel-action {display: block; float: left; height: 30px; min-width: 26px; text-align: center; line-height: 30px; padding-left: 3px; padding-right: 3px;} -.dashboard .panel-actions > a {color: #666} -.dashboard .panel-action-more {font-size: 12px; font-weight: 200} -.dashboard .panel-action:hover, .dashboard .panel-actions > .dropdown > a:hover {color: #333; background-color: #ddd; background-color: rgba(0,0,0,0.1)} -.dashboard .panel-title {font-size: 13px; color: #333} -.dashboard a.panel-title > .icon-double-angle-right {position: relative; filter: alpha(opacity=0); opacity: 0; transition: opacity .2s, left .2s; left: -5px} -.dashboard .panel:hover a.panel-title > .icon-double-angle-right {filter: alpha(opacity=100); opacity: 1; left: 0} -.dashboard a.panel-title:hover {color: #1a53ff} -.dashboard .panel {box-shadow: 0 1px 3px rgba(0,0,0,.05); position: relative; overflow-x: hidden;} -.dashboard .panel.with-fixed-header {overflow-x: hidden;} -.dashboard .panel-heading + .panel-body {position: absolute; left: 0; top: 30px; right: 0; bottom: 0} -.dashboard .panel-dragging-shadow {position: absolute;} -.dashboard-empty-message {text-align: center; margin-top: 100px;} -.dashboard-empty-message > h5 {margin-bottom: 20px;} -.dashboard-actions {position: absolute; top:-20px; right:-10px;} -.dashboard-actions > a {display: inline-block; width: 40px; height: 20px; text-align: center; color: #999; border: 1px solid #999; line-height: 20px; background: #1a4f85; color: #fff} -.dashboard-actions > a:hover {background: #2e6dad; border-color: #2e6dad} - -#wrap .outer {background-color: #fafafa;} -#wrap .outer > .dashboard {margin-left: -10px; margin-right: -10px;} - -/* panel style */ -.panel-block .table th {background-color: #fafafa} -.panel-primary {border-color: transparent;!important;} -.panel-success > .panel-heading, -.panel-warning > .panel-heading, -.panel-primary > .panel-heading, -.panel-info > .panel-heading, -.panel-danger > .panel-heading {color: #333; border: none; border-bottom: 1px solid rgba(0,0,0,.04);} -.panel-success, .panel-success .table-header-fixed th {background: #d1fecb!important; border-color: #b0e4ac!important} -.panel-success > .panel-heading {background: #c5f7c1!important; } -.panel-warning, .panel-warning .table-header-fixed th {background: #fdfdc7!important; border-color: #e1e09a!important} -.panel-warning > .panel-heading {background: #f8f7b6!important;} -.panel-primary, .panel-primary .table-header-fixed th {background: #d8f2fa!important; border-color: #badfeb!important} -.panel-primary > .panel-heading {background: #c9ecf8!important; color: #333!important; border:none!important;} -.panel-info, .panel-info .table-header-fixed th {background: #dcd8fe!important; border-color: #d0c9ee!important} -.panel-info > .panel-heading {background: #d4cdf3!important;} -.panel-danger, .panel-danger .table-header-fixed th {background: #f5d0f5!important; border-color: #e9b9e9!important} -.panel-danger > .panel-heading {background: #f1c3f1!important;} -.panel-success .table td, .panel-success .table th, -.panel-warning .table td, .panel-warning .table th, -.panel-primary .table td, .panel-primary .table th, -.panel-info .table td, .panel-info .table th, -.panel-danger .table td, .panel-danger .table th {border: none; background-color: transparent} -.panel-success .table tr:nth-child(even) > td, .panel-success .table th, -.panel-warning .table tr:nth-child(even) > td, .panel-warning .table th, -.panel-primary .table tr:nth-child(even) > td, .panel-primary .table th, -.panel-info .table tr:nth-child(even) > td, .panel-info .table th, -.panel-danger .table tr:nth-child(even) > td, .panel-danger .table th {background: rgba(255,255,255,.25);} -.panel-success .table tr:nth-child(odd) > td, -.panel-warning .table tr:nth-child(odd) > td, -.panel-primary .table tr:nth-child(odd) > td, -.panel-info .table tr:nth-child(odd) > td, -.panel-danger .table tr:nth-child(odd) > td {background: rgba(0,0,0,.03);} -.panel-success .table tr:last-child > td, -.panel-warning .table tr:last-child > td, -.panel-primary .table tr:last-child > td, -.panel-info .table tr:last-child > td -.panel-danger .table tr:last-child > td {border-bottom: 1px solid rgba(0,0,0,0.05)} -.panel-success .table tr:hover > th, -.panel-warning .table tr:hover > th, -.panel-primary .table tr:hover > th, -.panel-info .table tr:hover > th, -.panel-danger .table tr:hover > th {background: none;} -.panel-success .table.table-hover tr:hover > td, -.panel-warning .table.table-hover tr:hover > td, -.panel-primary .table.table-hover tr:hover > td, -.panel-info .table.table-hover tr:hover > td, -.panel-danger .table.table-hover tr:hover > td {background: rgba(255,255,255,.4);} - -.block.input-group-btn .btn-success {background: #d1fecb; color: #333; text-shadow: none; border-color: #ccc} -.block.input-group-btn .btn-warning {background: #fdfdc7; color: #333; text-shadow: none; border-color: #ccc} -.block.input-group-btn .btn-info {background: #dcd8fe; color: #333; text-shadow: none; border-color: #ccc} -.block.input-group-btn .btn-danger {background: #f5d0f5; color: #333; text-shadow: none; border-color: #ccc} -.block.input-group-btn .btn-primary, .block.input-group-btn .btn-primary:focus {background: #d8f2fa; color: #333; text-shadow: none; border-color: #ccc} -.block.input-group-btn .btn-success:hover {border-color: #aaa} -.block.input-group-btn .btn-warning:hover {border-color: #aaa} -.block.input-group-btn .btn-primary:hover {border-color: #aaa} -.block.input-group-btn .btn-info:hover {border-color: #aaa} -.block.input-group-btn .btn-danger:hover {border-color: #aaa} -.block.input-group-btn .btn-primary .caret, .block.input-group-btn .btn-success .caret, .block.input-group-btn .btn-warning .caret, .block.input-group-btn .btn-danger .caret, .block.input-group-btn .btn-info .caret {border-top-color: #333} diff --git a/module/block/js/admin.js b/module/block/js/admin.js index 39aec0f8ec..d5e5408db9 100644 --- a/module/block/js/admin.js +++ b/module/block/js/admin.js @@ -1,85 +1,92 @@ -/** - * Get all blocks. - * - * @param string|int $moduleID - * @access public - * @return void - */ -function getBlocks(moduleID) -{ - var moduleBlock = $('#modules').parent().parent().next(); - $(moduleBlock).hide(); - - $('#blockParam').empty(); - if(moduleID == '') return false; - - if(moduleID.indexOf('hiddenBlock') != -1) - { - getNotSourceParams('html', moduleID.replace('hiddenBlock', '')); - return true; - } - if(moduleID == 'html' || moduleID == 'dynamic' || moduleID == 'flowchart') - { - getNotSourceParams(moduleID, blockID); - return true; - } - - $.get(createLink('block', 'main', 'module=' + moduleID + '&id=' + blockID), {mode:'getblocklist'}, function(data) - { - $(moduleBlock).html(data); - $(moduleBlock).show(); - $.ajustModalPosition(); - }) -} - -/** - * Get rss and html params. - * - * @param string $type - * @access public - * @return void - */ -function getNotSourceParams(type, blockID) -{ - blockID = typeof(blockID) == 'undefined' ? 0 : blockID; - $.get(createLink('block', 'set', 'id=' + blockID + '&type=' + type), function(data) - { - $('#blockParam').html(data); - $.ajustModalPosition(); - }); -} - -/** - * Get block params. - * - * @param string $type - * @param int $moduleID - * @access public - * @return void - */ -function getBlockParams(type, moduleID) -{ - $('#blockParam').empty(); - - if(type == '') return; - - $.get(createLink('block', 'set', 'id=' + blockID + '&type=' + type + '&source=' + moduleID), function(data) - { - $('#blockParam').html(data); - $.ajustModalPosition(); - }); -} - $(function() { - $('#modules').change(function(){getBlocks($(this).val())}); - if($('#modules').size() > 0) getBlocks($('#modules').val()); + var $form = $('#blockAdminForm'); + $form.find('.chosen').chosen(); - $(document).on('click', '.dropdown-menu.buttons .btn', function() + // 用于动态加载区块列表及设置参数 + var $blocksList = $('#blocksList'); + var $blockParams = $('#blockParams'); + + var updateParams = function(data) { - var $this = $(this); - var group = $this.closest('.input-group-btn'); - group.find('.dropdown-toggle').removeClass().addClass('btn dropdown-toggle btn-' + $this.data('id')); - group.find('input[name^="params[color]"]').val($this.data('id')); + $blockParams.html(data); + $blockParams.find('.chosen').chosen(); + $.zui.ajustModalPosition(); + $form.removeClass('loading'); + $form.addClass('form-inited'); + $blockParams.find('input:first').focus(); + if($blockParams.find('#actionLink').size() > 0) $form.attr('action', $blockParams.find('#actionLink').val()); + }; + + // 获取 html 和 rss 区块参数 + var getNotSourceParams = function(type, blockID) + { + if (blockID === undefined) blockID = 0; + + $blockParams.empty(); + $form.removeClass('form-inited'); + + $.get(createLink('block', 'set', 'id=' + blockID + '&type=' + type), updateParams); + }; + + // 用于获取指定区块的设置参数 + var getBlockParams = function(type, moduleID) + { + $blockParams.empty(); + $form.removeClass('form-inited'); + + if(type == '') return; + $form.addClass('loading'); + $.get(createLink('block', 'set', 'id=' + blockID + '&type=' + type + '&source=' + moduleID), updateParams); + }; + + // 获取指定模块下所有可用的区块 + var getBlocks = function(moduleID) + { + $blocksList.data('module', moduleID).empty(); + $form.removeClass('form-inited'); + $blockParams.empty(); + if(!moduleID) return; + + $form.addClass('loading'); + + var onFinish = function() + { + $form.removeClass('loading'); + if($blocksList.find('#moduleBlock').val() != '') getBlockParams($blocksList.find('#moduleBlock').val(), $blocksList.data('module')); + }; + + if(moduleID.indexOf('hiddenBlock') != -1) + { + getNotSourceParams('html', moduleID.replace('hiddenBlock', ''), onFinish); + return true; + } + + if(moduleID == 'html' || moduleID == 'dynamic' || moduleID == 'flowchart' || moduleID == 'assigntome' || moduleID == 'welcome') + { + getNotSourceParams(moduleID, blockID, onFinish); + return true; + } + + $.get(createLink('block', 'main', 'module=' + moduleID + '&id=' + blockID), {mode:'getblocklist'}, function(data) + { + $blocksList.html(data); + $blocksList.find('.chosen').chosen(); + onFinish(); + $.zui.ajustModalPosition(); + }); + }; + + // 当模块选择变更时,刷新参数列表 + $('#modules').on('change', function() + { + getBlocks($(this).val()); }); -}) + + $blocksList.on('change', '#moduleBlock', function() + { + getBlockParams($(this).val(), $blocksList.data('module')); + }); + + if(blockID) setTimeout(function(){getBlocks($('#modules').val());}, 200); +}); diff --git a/module/block/js/dashboard.js b/module/block/js/dashboard.js index cc7d3f9861..cad8d173c9 100644 --- a/module/block/js/dashboard.js +++ b/module/block/js/dashboard.js @@ -7,16 +7,21 @@ */ function deleteBlock(index) { - $.getJSON(createLink('block', 'delete', 'index=' + index + '&module=' + module), function(data) - { - if(data.result != 'success') - { - alert(data.message); - return false; - } - - checkEmpty(); - }) + if(confirm(config.confirmRemoveBlock)) + { + $.getJSON(createLink('block', 'delete', 'index=' + index + '&module=' + module), function(data) + { + if(data.result != 'success') + { + alert(data.message); + return false; + } + else + { + $('#block' + index).remove(); + } + }); + } } /** @@ -40,19 +45,6 @@ function sortBlocks(orders) }); } -/** - * Check dashboard wether is empty - * @access public - * @return void - */ -function checkEmpty() -{ - var $dashboard = $('#dashboard'); - var hasBlocks = !!$dashboard.children('.row').children().length; - $dashboard.find('.dashboard-empty-message').toggleClass('hide', hasBlocks); - if(!hasBlocks) $dashboard.find('.dashboard-actions').addClass('hide'); -} - /** * Resize block * @param object $event @@ -168,28 +160,27 @@ function hiddenBlock(index) $(function() { - var $dashboard = $('#dashboard').dashboard( - { - height : 240, - draggable : !useGuest, - shadowType : false, - afterOrdered : sortBlocks, - afterPanelRemoved : deleteBlock, - sensitive : true, - panelRemovingTip : config.confirmRemoveBlock, - resizable : !useGuest, - onResize : resizeBlock, - afterRefresh : function(e) - { - var $sortTable = e.$panel.find('.tablesorter'); - if($sortTable.length) $sortTable.sortTable(); - initTableHeader(); - } - }); +// var $dashboard = $('#dashboard').dashboard( +// { +// height : 240, +// draggable : !useGuest, +// shadowType : false, +// afterOrdered : sortBlocks, +// afterPanelRemoved : deleteBlock, +// sensitive : true, +// panelRemovingTip : config.confirmRemoveBlock, +// resizable : !useGuest, +// onResize : resizeBlock, +// afterRefresh : function(e) +// { +// var $sortTable = e.$panel.find('.tablesorter'); +// if($sortTable.length) $sortTable.sortTable(); +// initTableHeader(); +// } +// }); +// +// // $dashboard.find('ul.dashboard-actions').addClass('hide').children('li').addClass('right').appendTo($('#modulemenu > .nav')); +// $dashboard.find('[data-toggle=tooltip]').tooltip({container: 'body'}); - // $dashboard.find('ul.dashboard-actions').addClass('hide').children('li').addClass('right').appendTo($('#modulemenu > .nav')); - $dashboard.find('[data-toggle=tooltip]').tooltip({container: 'body'}); - - checkEmpty(); - initTableHeader(); +// initTableHeader(); }); diff --git a/module/block/lang/en.php b/module/block/lang/en.php index c34dbae5b6..aa74dd0005 100644 --- a/module/block/lang/en.php +++ b/module/block/lang/en.php @@ -29,7 +29,17 @@ $lang->block->lblBlock = 'Block'; $lang->block->lblNum = 'Number'; $lang->block->lblHtml = 'HTML'; $lang->block->dynamic = 'Dynamic'; +$lang->block->assignToMe = 'Assign To Me'; $lang->block->lblFlowchart = 'Workflow'; +$lang->block->welcome = 'Welcome'; + +$lang->block->leftToday = 'The rest of the work today'; +$lang->block->myTask = 'My Task'; +$lang->block->myStory = 'My Story'; +$lang->block->myBug = 'My Bug'; +$lang->block->myProject = 'My ' . $lang->projectCommon; +$lang->block->myProduct = 'My ' . $lang->productCommon; +$lang->block->delayed = 'Delayed'; $lang->block->params = new stdclass(); $lang->block->params->name = 'Name'; @@ -38,15 +48,15 @@ $lang->block->params->value = 'Value'; $lang->block->createBlock = 'Add'; $lang->block->editBlock = 'Edit'; $lang->block->ordersSaved = 'Order is saved.'; -$lang->block->confirmRemoveBlock = 'Do you want to remove Block【{0}】?'; +$lang->block->confirmRemoveBlock = 'Do you want to remove Block?'; $lang->block->closeForever = 'Permanent Close'; $lang->block->confirmClose = 'Do you want to permanently close this block? Once done, it is not available to anyone. It can be activiated at Admin->Custom.'; $lang->block->remove = 'Remove'; $lang->block->refresh = 'Refresh'; $lang->block->hidden = 'Hide'; -$lang->block->dynamicInfo = "%s, %s %s %s %s."; +$lang->block->dynamicInfo = "%s, %s %s %s %s"; -$lang->block->default['product']['1']['title'] = 'Open' . $lang->productCommon; +$lang->block->default['product']['1']['title'] = 'Open ' . $lang->productCommon . 's'; $lang->block->default['product']['1']['block'] = 'list'; $lang->block->default['product']['1']['grid'] = 8; @@ -61,7 +71,7 @@ $lang->block->default['product']['2']['params']['num'] = 15; $lang->block->default['product']['2']['params']['orderBy'] = 'id_desc'; $lang->block->default['product']['2']['params']['type'] = 'assignedTo'; -$lang->block->default['project']['1']['title'] = 'Doing' . $lang->projectCommon; +$lang->block->default['project']['1']['title'] = 'Active ' . $lang->projectCommon . 's'; $lang->block->default['project']['1']['block'] = 'list'; $lang->block->default['project']['1']['grid'] = 8; @@ -101,31 +111,33 @@ $lang->block->default['qa']['3']['params']['num'] = 15; $lang->block->default['qa']['3']['params']['orderBy'] = 'id_desc'; $lang->block->default['qa']['3']['params']['type'] = 'wait'; -$lang->block->default['full']['my']['1']['title'] = 'Flowchart'; -$lang->block->default['full']['my']['1']['block'] = 'flowchart'; +$lang->block->default['full']['my']['1']['title'] = 'Welcome'; +$lang->block->default['full']['my']['1']['block'] = 'welcome'; $lang->block->default['full']['my']['1']['grid'] = 8; $lang->block->default['full']['my']['1']['source'] = ''; $lang->block->default['full']['my']['2']['title'] = 'Dynamic'; $lang->block->default['full']['my']['2']['block'] = 'dynamic'; $lang->block->default['full']['my']['2']['grid'] = 4; $lang->block->default['full']['my']['2']['source'] = ''; -$lang->block->default['full']['my']['3'] = $lang->block->default['project']['1']; -$lang->block->default['full']['my']['3']['source'] = 'project'; -$lang->block->default['full']['my']['4']['title'] = 'My To-Dos'; -$lang->block->default['full']['my']['4']['block'] = 'list'; -$lang->block->default['full']['my']['4']['grid'] = 4; -$lang->block->default['full']['my']['4']['source'] = 'todo'; -$lang->block->default['full']['my']['4']['params']['num'] = '20'; -$lang->block->default['full']['my']['5'] = $lang->block->default['product']['1']; -$lang->block->default['full']['my']['5']['source'] = 'product'; -$lang->block->default['full']['my']['6'] = $lang->block->default['project']['2']; +$lang->block->default['full']['my']['3']['title'] = 'Flowchart'; +$lang->block->default['full']['my']['3']['block'] = 'flowchart'; +$lang->block->default['full']['my']['3']['grid'] = 8; +$lang->block->default['full']['my']['3']['source'] = ''; +$lang->block->default['full']['my']['5']['title'] = 'My Todos'; +$lang->block->default['full']['my']['5']['block'] = 'list'; +$lang->block->default['full']['my']['5']['grid'] = 4; +$lang->block->default['full']['my']['5']['source'] = 'todo'; +$lang->block->default['full']['my']['5']['params']['num'] = '20'; +$lang->block->default['full']['my']['6'] = $lang->block->default['project']['1']; $lang->block->default['full']['my']['6']['source'] = 'project'; -$lang->block->default['full']['my']['7'] = $lang->block->default['qa']['1']; -$lang->block->default['full']['my']['7']['source'] = 'qa'; -$lang->block->default['full']['my']['8'] = $lang->block->default['product']['2']; +$lang->block->default['full']['my']['7'] = $lang->block->default['project']['2']; +$lang->block->default['full']['my']['7']['source'] = 'project'; +$lang->block->default['full']['my']['8'] = $lang->block->default['product']['1']; $lang->block->default['full']['my']['8']['source'] = 'product'; -$lang->block->default['full']['my']['9'] = $lang->block->default['qa']['2']; -$lang->block->default['full']['my']['9']['source'] = 'qa'; +$lang->block->default['full']['my']['9'] = $lang->block->default['product']['2']; +$lang->block->default['full']['my']['9']['source'] = 'product'; +$lang->block->default['full']['my']['10'] = $lang->block->default['qa']['2']; +$lang->block->default['full']['my']['10']['source'] = 'qa'; $lang->block->default['onlyTest']['my']['1'] = $lang->block->default['qa']['1']; $lang->block->default['onlyTest']['my']['1']['source'] = 'qa'; @@ -134,7 +146,7 @@ $lang->block->default['onlyTest']['my']['2']['title'] = 'Dynamic'; $lang->block->default['onlyTest']['my']['2']['block'] = 'dynamic'; $lang->block->default['onlyTest']['my']['2']['grid'] = 4; $lang->block->default['onlyTest']['my']['2']['source'] = ''; -$lang->block->default['onlyTest']['my']['3']['title'] = 'My To-Dos'; +$lang->block->default['onlyTest']['my']['3']['title'] = 'My Todo'; $lang->block->default['onlyTest']['my']['3']['block'] = 'list'; $lang->block->default['onlyTest']['my']['3']['grid'] = 6; $lang->block->default['onlyTest']['my']['3']['source'] = 'todo'; @@ -150,7 +162,7 @@ $lang->block->default['onlyStory']['my']['2']['title'] = 'Dynamic'; $lang->block->default['onlyStory']['my']['2']['block'] = 'dynamic'; $lang->block->default['onlyStory']['my']['2']['grid'] = 4; $lang->block->default['onlyStory']['my']['2']['source'] = ''; -$lang->block->default['onlyStory']['my']['3']['title'] = 'My To-Dos'; +$lang->block->default['onlyStory']['my']['3']['title'] = 'My Todo'; $lang->block->default['onlyStory']['my']['3']['block'] = 'list'; $lang->block->default['onlyStory']['my']['3']['grid'] = 6; $lang->block->default['onlyStory']['my']['3']['source'] = 'todo'; @@ -166,7 +178,7 @@ $lang->block->default['onlyTask']['my']['2']['title'] = 'Dynamic'; $lang->block->default['onlyTask']['my']['2']['block'] = 'dynamic'; $lang->block->default['onlyTask']['my']['2']['grid'] = 4; $lang->block->default['onlyTask']['my']['2']['source'] = ''; -$lang->block->default['onlyTask']['my']['3']['title'] = 'My To-Dos'; +$lang->block->default['onlyTask']['my']['3']['title'] = 'My Todo'; $lang->block->default['onlyTask']['my']['3']['block'] = 'list'; $lang->block->default['onlyTask']['my']['3']['grid'] = 6; $lang->block->default['onlyTask']['my']['3']['source'] = 'todo'; @@ -181,7 +193,7 @@ $lang->block->orderBy = 'Order by'; $lang->block->availableBlocks = new stdclass(); -$lang->block->availableBlocks->todo = 'My To-Dos'; +$lang->block->availableBlocks->todo = 'My Todo'; $lang->block->availableBlocks->task = 'My Tasks'; $lang->block->availableBlocks->bug = 'My Bugs'; $lang->block->availableBlocks->case = 'My Cases'; @@ -196,7 +208,7 @@ $lang->block->availableBlocks->testtask = 'Test Builds'; $lang->block->moduleList['product'] = $lang->productCommon; $lang->block->moduleList['project'] = $lang->projectCommon; $lang->block->moduleList['qa'] = 'QA'; -$lang->block->moduleList['todo'] = 'To-Dos'; +$lang->block->moduleList['todo'] = 'Todo'; $lang->block->modules['product'] = new stdclass(); $lang->block->modules['product']->availableBlocks = new stdclass(); @@ -216,7 +228,7 @@ $lang->block->modules['qa']->availableBlocks->case = 'Cases'; $lang->block->modules['qa']->availableBlocks->testtask = 'Test Builds'; $lang->block->modules['todo'] = new stdclass(); $lang->block->modules['todo']->availableBlocks = new stdclass(); -$lang->block->modules['todo']->availableBlocks->list = 'To-Dos'; +$lang->block->modules['todo']->availableBlocks->list = 'Todo'; $lang->block->orderByList = new stdclass(); @@ -256,6 +268,10 @@ $lang->block->orderByList->story['status_desc'] = 'Status Descending'; $lang->block->orderByList->story['stage_asc'] = 'Stage Ascending'; $lang->block->orderByList->story['stage_desc'] = 'Stage Descending'; +$lang->block->todoNum = 'Todo Number'; +$lang->block->taskNum = 'Task Number'; +$lang->block->bugNum = 'Bug Number'; + $lang->block->typeList = new stdclass(); $lang->block->typeList->task['assignedTo'] = 'Assigned to Me'; @@ -282,7 +298,7 @@ $lang->block->typeList->product['closed'] = 'Closed'; $lang->block->typeList->product['all'] = 'All'; $lang->block->typeList->product['involved'] = 'Involved'; -$lang->block->typeList->project['undone'] = 'Undone'; +$lang->block->typeList->project['undone'] = 'Unfinished'; $lang->block->typeList->project['isdoing'] = 'Doing'; $lang->block->typeList->project['all'] = 'All'; $lang->block->typeList->project['involved'] = 'Involved'; @@ -309,6 +325,14 @@ $lang->block->modules['common'] = new stdclass(); $lang->block->modules['common']->moreLinkList = new stdclass(); $lang->block->modules['common']->moreLinkList->dynamic = 'company|dynamic|'; +$lang->block->welcomeList['06:00'] = 'Good morning, %s'; +$lang->block->welcomeList['11:30'] = 'Good noon, %s'; +$lang->block->welcomeList['13:30'] = 'Good afternoon, %s'; +$lang->block->welcomeList['19:00'] = 'Good evening, %s'; + +$lang->block->gridOptions[8] = 'Left'; +$lang->block->gridOptions[4] = 'Right'; + $lang->block->flowchart = array(); $lang->block->flowchart[] = array('Administration', 'Manage a Company', 'Add Users', 'Maintain Privileges'); $lang->block->flowchart[] = array($lang->productCommon . ' Manager', 'Add ' . $lang->productCommon, 'Maintain Modules', 'Maintain Plans', 'Maintain Stories', 'Create Release'); diff --git a/module/block/lang/zh-cn.php b/module/block/lang/zh-cn.php index ce3758f2a0..622c452691 100644 --- a/module/block/lang/zh-cn.php +++ b/module/block/lang/zh-cn.php @@ -13,7 +13,7 @@ $lang->block = new stdclass(); $lang->block->common = '区块'; $lang->block->name = '区块名称'; $lang->block->style = '外观'; -$lang->block->grid = '宽度'; +$lang->block->grid = '位置'; $lang->block->color = '颜色'; $lang->block->account = '所属用户'; @@ -29,7 +29,17 @@ $lang->block->lblBlock = '区块'; $lang->block->lblNum = '条数'; $lang->block->lblHtml = 'HTML内容'; $lang->block->dynamic = '最新动态'; +$lang->block->assignToMe = '指派给我'; $lang->block->lblFlowchart = '流程图'; +$lang->block->welcome = '欢迎总览'; + +$lang->block->leftToday = '今天剩余工作总计'; +$lang->block->myTask = '我的任务'; +$lang->block->myStory = '我的需求'; +$lang->block->myBug = '我的BUG'; +$lang->block->myProject = '进行中的' . $lang->projectCommon; +$lang->block->myProduct = '未关闭的' . $lang->productCommon; +$lang->block->delayed = '已延期'; $lang->block->params = new stdclass(); $lang->block->params->name = '参数名称'; @@ -38,13 +48,13 @@ $lang->block->params->value = '参数值'; $lang->block->createBlock = '添加区块'; $lang->block->editBlock = '编辑区块'; $lang->block->ordersSaved = '排序已保存'; -$lang->block->confirmRemoveBlock = '确定移除区块【{0}】吗?'; +$lang->block->confirmRemoveBlock = '确定移除区块吗?'; $lang->block->closeForever = '永久关闭'; $lang->block->confirmClose = '确定永久关闭该区块吗?闭后所有人都将无法使用该区块,可以在后台自定义中打开'; $lang->block->remove = '移除'; $lang->block->refresh = '刷新'; $lang->block->hidden = '隐藏'; -$lang->block->dynamicInfo = "%s, %s %s %s %s。"; +$lang->block->dynamicInfo = "%s, %s %s %s %s"; $lang->block->default['product']['1']['title'] = '未关闭的' . $lang->productCommon; $lang->block->default['product']['1']['block'] = 'list'; @@ -101,31 +111,33 @@ $lang->block->default['qa']['3']['params']['num'] = 15; $lang->block->default['qa']['3']['params']['orderBy'] = 'id_desc'; $lang->block->default['qa']['3']['params']['type'] = 'wait'; -$lang->block->default['full']['my']['1']['title'] = '流程图'; -$lang->block->default['full']['my']['1']['block'] = 'flowchart'; +$lang->block->default['full']['my']['1']['title'] = '欢迎'; +$lang->block->default['full']['my']['1']['block'] = 'welcome'; $lang->block->default['full']['my']['1']['grid'] = 8; $lang->block->default['full']['my']['1']['source'] = ''; $lang->block->default['full']['my']['2']['title'] = '最新动态'; $lang->block->default['full']['my']['2']['block'] = 'dynamic'; $lang->block->default['full']['my']['2']['grid'] = 4; $lang->block->default['full']['my']['2']['source'] = ''; -$lang->block->default['full']['my']['3'] = $lang->block->default['project']['1']; -$lang->block->default['full']['my']['3']['source'] = 'project'; -$lang->block->default['full']['my']['4']['title'] = '我的待办'; -$lang->block->default['full']['my']['4']['block'] = 'list'; -$lang->block->default['full']['my']['4']['grid'] = 4; -$lang->block->default['full']['my']['4']['source'] = 'todo'; -$lang->block->default['full']['my']['4']['params']['num'] = '20'; -$lang->block->default['full']['my']['5'] = $lang->block->default['product']['1']; -$lang->block->default['full']['my']['5']['source'] = 'product'; -$lang->block->default['full']['my']['6'] = $lang->block->default['project']['2']; +$lang->block->default['full']['my']['3']['title'] = '流程图'; +$lang->block->default['full']['my']['3']['block'] = 'flowchart'; +$lang->block->default['full']['my']['3']['grid'] = 8; +$lang->block->default['full']['my']['3']['source'] = ''; +$lang->block->default['full']['my']['5']['title'] = '我的待办'; +$lang->block->default['full']['my']['5']['block'] = 'list'; +$lang->block->default['full']['my']['5']['grid'] = 4; +$lang->block->default['full']['my']['5']['source'] = 'todo'; +$lang->block->default['full']['my']['5']['params']['num'] = '20'; +$lang->block->default['full']['my']['6'] = $lang->block->default['project']['1']; $lang->block->default['full']['my']['6']['source'] = 'project'; -$lang->block->default['full']['my']['7'] = $lang->block->default['qa']['1']; -$lang->block->default['full']['my']['7']['source'] = 'qa'; -$lang->block->default['full']['my']['8'] = $lang->block->default['product']['2']; +$lang->block->default['full']['my']['7'] = $lang->block->default['project']['2']; +$lang->block->default['full']['my']['7']['source'] = 'project'; +$lang->block->default['full']['my']['8'] = $lang->block->default['product']['1']; $lang->block->default['full']['my']['8']['source'] = 'product'; -$lang->block->default['full']['my']['9'] = $lang->block->default['qa']['2']; -$lang->block->default['full']['my']['9']['source'] = 'qa'; +$lang->block->default['full']['my']['9'] = $lang->block->default['product']['2']; +$lang->block->default['full']['my']['9']['source'] = 'product'; +$lang->block->default['full']['my']['10'] = $lang->block->default['qa']['2']; +$lang->block->default['full']['my']['10']['source'] = 'qa'; $lang->block->default['onlyTest']['my']['1'] = $lang->block->default['qa']['1']; $lang->block->default['onlyTest']['my']['1']['source'] = 'qa'; @@ -256,6 +268,10 @@ $lang->block->orderByList->story['status_desc'] = '状态倒序'; $lang->block->orderByList->story['stage_asc'] = '阶段正序'; $lang->block->orderByList->story['stage_desc'] = '阶段倒序'; +$lang->block->todoNum = '待办数'; +$lang->block->taskNum = '任务数'; +$lang->block->bugNum = 'Bug数'; + $lang->block->typeList = new stdclass(); $lang->block->typeList->task['assignedTo'] = '指派给我'; @@ -309,6 +325,14 @@ $lang->block->modules['common'] = new stdclass(); $lang->block->modules['common']->moreLinkList = new stdclass(); $lang->block->modules['common']->moreLinkList->dynamic = 'company|dynamic|'; +$lang->block->welcomeList['06:00'] = '%s,早上好!'; +$lang->block->welcomeList['11:30'] = '%s,中文好!'; +$lang->block->welcomeList['13:30'] = '%s,下午好!'; +$lang->block->welcomeList['19:00'] = '%s,晚上好!'; + +$lang->block->gridOptions[8] = '左侧'; +$lang->block->gridOptions[4] = '右侧'; + $lang->block->flowchart = array(); $lang->block->flowchart[] = array('管理员', '维护公司', '添加用户', '维护权限'); $lang->block->flowchart[] = array($lang->productCommon . '经理', '创建' . $lang->productCommon, '维护模块', '维护计划', '维护需求', '创建发布'); diff --git a/module/block/lang/zh-tw.php b/module/block/lang/zh-tw.php index f81409d8af..3a302336cf 100644 --- a/module/block/lang/zh-tw.php +++ b/module/block/lang/zh-tw.php @@ -13,7 +13,7 @@ $lang->block = new stdclass(); $lang->block->common = '區塊'; $lang->block->name = '區塊名稱'; $lang->block->style = '外觀'; -$lang->block->grid = '寬度'; +$lang->block->grid = '位置'; $lang->block->color = '顏色'; $lang->block->account = '所屬用戶'; @@ -29,7 +29,17 @@ $lang->block->lblBlock = '區塊'; $lang->block->lblNum = '條數'; $lang->block->lblHtml = 'HTML內容'; $lang->block->dynamic = '最新動態'; +$lang->block->assignToMe = '指派給我'; $lang->block->lblFlowchart = '流程圖'; +$lang->block->welcome = '歡迎總覽'; + +$lang->block->leftToday = '今天剩餘工作總計'; +$lang->block->myTask = '我的任務'; +$lang->block->myStory = '我的需求'; +$lang->block->myBug = '我的BUG'; +$lang->block->myProject = '進行中的' . $lang->projectCommon; +$lang->block->myProduct = '未關閉的' . $lang->productCommon; +$lang->block->delayed = '已延期'; $lang->block->params = new stdclass(); $lang->block->params->name = '參數名稱'; @@ -38,13 +48,13 @@ $lang->block->params->value = '參數值'; $lang->block->createBlock = '添加區塊'; $lang->block->editBlock = '編輯區塊'; $lang->block->ordersSaved = '排序已保存'; -$lang->block->confirmRemoveBlock = '確定移除區塊【{0}】嗎?'; +$lang->block->confirmRemoveBlock = '確定移除區塊嗎?'; $lang->block->closeForever = '永久關閉'; $lang->block->confirmClose = '確定永久關閉該區塊嗎?閉後所有人都將無法使用該區塊,可以在後台自定義中打開'; $lang->block->remove = '移除'; $lang->block->refresh = '刷新'; $lang->block->hidden = '隱藏'; -$lang->block->dynamicInfo = "%s, %s %s %s %s。"; +$lang->block->dynamicInfo = "%s, %s %s %s %s"; $lang->block->default['product']['1']['title'] = '未關閉的' . $lang->productCommon; $lang->block->default['product']['1']['block'] = 'list'; @@ -101,31 +111,33 @@ $lang->block->default['qa']['3']['params']['num'] = 15; $lang->block->default['qa']['3']['params']['orderBy'] = 'id_desc'; $lang->block->default['qa']['3']['params']['type'] = 'wait'; -$lang->block->default['full']['my']['1']['title'] = '流程圖'; -$lang->block->default['full']['my']['1']['block'] = 'flowchart'; +$lang->block->default['full']['my']['1']['title'] = '歡迎'; +$lang->block->default['full']['my']['1']['block'] = 'welcome'; $lang->block->default['full']['my']['1']['grid'] = 8; $lang->block->default['full']['my']['1']['source'] = ''; $lang->block->default['full']['my']['2']['title'] = '最新動態'; $lang->block->default['full']['my']['2']['block'] = 'dynamic'; $lang->block->default['full']['my']['2']['grid'] = 4; $lang->block->default['full']['my']['2']['source'] = ''; -$lang->block->default['full']['my']['3'] = $lang->block->default['project']['1']; -$lang->block->default['full']['my']['3']['source'] = 'project'; -$lang->block->default['full']['my']['4']['title'] = '我的待辦'; -$lang->block->default['full']['my']['4']['block'] = 'list'; -$lang->block->default['full']['my']['4']['grid'] = 4; -$lang->block->default['full']['my']['4']['source'] = 'todo'; -$lang->block->default['full']['my']['4']['params']['num'] = '20'; -$lang->block->default['full']['my']['5'] = $lang->block->default['product']['1']; -$lang->block->default['full']['my']['5']['source'] = 'product'; -$lang->block->default['full']['my']['6'] = $lang->block->default['project']['2']; +$lang->block->default['full']['my']['3']['title'] = '流程圖'; +$lang->block->default['full']['my']['3']['block'] = 'flowchart'; +$lang->block->default['full']['my']['3']['grid'] = 8; +$lang->block->default['full']['my']['3']['source'] = ''; +$lang->block->default['full']['my']['5']['title'] = '我的待辦'; +$lang->block->default['full']['my']['5']['block'] = 'list'; +$lang->block->default['full']['my']['5']['grid'] = 4; +$lang->block->default['full']['my']['5']['source'] = 'todo'; +$lang->block->default['full']['my']['5']['params']['num'] = '20'; +$lang->block->default['full']['my']['6'] = $lang->block->default['project']['1']; $lang->block->default['full']['my']['6']['source'] = 'project'; -$lang->block->default['full']['my']['7'] = $lang->block->default['qa']['1']; -$lang->block->default['full']['my']['7']['source'] = 'qa'; -$lang->block->default['full']['my']['8'] = $lang->block->default['product']['2']; +$lang->block->default['full']['my']['7'] = $lang->block->default['project']['2']; +$lang->block->default['full']['my']['7']['source'] = 'project'; +$lang->block->default['full']['my']['8'] = $lang->block->default['product']['1']; $lang->block->default['full']['my']['8']['source'] = 'product'; -$lang->block->default['full']['my']['9'] = $lang->block->default['qa']['2']; -$lang->block->default['full']['my']['9']['source'] = 'qa'; +$lang->block->default['full']['my']['9'] = $lang->block->default['product']['2']; +$lang->block->default['full']['my']['9']['source'] = 'product'; +$lang->block->default['full']['my']['10'] = $lang->block->default['qa']['2']; +$lang->block->default['full']['my']['10']['source'] = 'qa'; $lang->block->default['onlyTest']['my']['1'] = $lang->block->default['qa']['1']; $lang->block->default['onlyTest']['my']['1']['source'] = 'qa'; @@ -256,6 +268,10 @@ $lang->block->orderByList->story['status_desc'] = '狀態倒序'; $lang->block->orderByList->story['stage_asc'] = '階段正序'; $lang->block->orderByList->story['stage_desc'] = '階段倒序'; +$lang->block->todoNum = '待辦數'; +$lang->block->taskNum = '任務數'; +$lang->block->bugNum = 'Bug數'; + $lang->block->typeList = new stdclass(); $lang->block->typeList->task['assignedTo'] = '指派給我'; @@ -302,13 +318,21 @@ $lang->block->modules['project']->moreLinkList->task = 'my|task|type=%s'; $lang->block->modules['qa']->moreLinkList = new stdclass(); $lang->block->modules['qa']->moreLinkList->bug = 'my|bug|type=%s'; $lang->block->modules['qa']->moreLinkList->case = 'my|testcase|type=%s'; -$lang->block->modules['qa']->moreLinkList->testtask = 'my|testtask|type=%s'; +$lang->block->modules['qa']->moreLinkList->testtask = 'testtask|browse|type=%s'; $lang->block->modules['todo']->moreLinkList = new stdclass(); $lang->block->modules['todo']->moreLinkList->list = 'my|todo|type=all'; $lang->block->modules['common'] = new stdclass(); $lang->block->modules['common']->moreLinkList = new stdclass(); $lang->block->modules['common']->moreLinkList->dynamic = 'company|dynamic|'; +$lang->block->welcomeList['06:00'] = '%s,早上好!'; +$lang->block->welcomeList['11:30'] = '%s,中文好!'; +$lang->block->welcomeList['13:30'] = '%s,下午好!'; +$lang->block->welcomeList['19:00'] = '%s,晚上好!'; + +$lang->block->gridOptions[8] = '左側'; +$lang->block->gridOptions[4] = '右側'; + $lang->block->flowchart = array(); $lang->block->flowchart[] = array('管理員', '維護公司', '添加用戶', '維護權限'); $lang->block->flowchart[] = array($lang->productCommon . '經理', '創建' . $lang->productCommon, '維護模組', '維護計劃', '維護需求', '創建發佈'); diff --git a/module/block/model.php b/module/block/model.php index b05b516e77..20054b403a 100644 --- a/module/block/model.php +++ b/module/block/model.php @@ -35,7 +35,7 @@ class blockModel extends model ->setDefault('source', $source) ->setDefault('block', $type) ->setDefault('params', array()) - ->remove('uid') + ->remove('uid,actionLink,modules,moduleBlock') ->get(); if($block) $data->height = $block->height; @@ -408,6 +408,23 @@ class blockModel extends model return json_encode($this->onlyNumParams($module, $params)); } + public function getAssignToMeParams() + { + $params->todoNum['name'] = $this->lang->block->todoNum; + $params->todoNum['default'] = 20; + $params->todoNum['control'] = 'input'; + + $params->taskNum['name'] = $this->lang->block->taskNum; + $params->taskNum['default'] = 20; + $params->taskNum['control'] = 'input'; + + $params->bugNum['name'] = $this->lang->block->bugNum; + $params->bugNum['default'] = 20; + $params->bugNum['control'] = 'input'; + + return json_encode($params); + } + /** * Get closed block pairs. * @@ -457,4 +474,16 @@ class blockModel extends model $params->num['control'] = 'input'; return $params; } + + /** + * Check whether long block. + * + * @param object $block + * @access public + * @return book + */ + public function isLongBlock($block) + { + return $block->grid >= 6; + } } diff --git a/module/block/view/admin.html.php b/module/block/view/admin.html.php index 463ebbff46..9cac5bec90 100644 --- a/module/block/view/admin.html.php +++ b/module/block/view/admin.html.php @@ -10,21 +10,36 @@ * @link http://www.ranzhico.com */ ?> +app->getWebRoot(); +$jsRoot = $webRoot . "js/"; +include '../../common/view/chosen.html.php'; +?> + +
+ +
+ source != '' ? $block->source : $block->block; + ?> + +
+
+ + +
+ + +
+ +
+
+   + +
+
+ -
backup->time?> backup->files?> backup->size?>actions?>actions?>
{$this->lang->block->lblBlock}' . html::select('moduleBlock', $blockPairs, ($block and $block->source != '') ? $block->block : '', "class='form-control' onchange='getBlockParams(this.value, \"$module\")'") . '
- - - - - source != '' ? $block->source : $block->block; - ?> - - - - -
block->lblModule; ?>
-
diff --git a/module/block/view/bugblock.html.php b/module/block/view/bugblock.html.php index aaa394eed3..8490075177 100644 --- a/module/block/view/bugblock.html.php +++ b/module/block/view/bugblock.html.php @@ -10,30 +10,40 @@ * @link http://www.ranzhi.org */ ?> - - - - - - - - - - - - get->entry}'" : ''; - $viewLink = $this->createLink('bug', 'view', "bugID={$bug->id}"); - ?> - > - - - - - - - -
idAB?>priAB?> bug->title;?>bug->severityAB?>bug->statusAB;?>
id;?>bug->priList, $bug->pri, $bug->pri)?>title?>bug->severityList, $bug->severity, $bug->severity)?>bug->statusList, $bug->status, $bug->status)?>
- +
+ '> + + + + + + + + + + + + + + get->entry}'" : ''; + $viewLink = $this->createLink('bug', 'view', "bugID={$bug->id}"); + ?> + > + + + + + + + + + + +
idAB?>priAB?>bug->severityAB?>bug->title;?>bug->statusAB;?>
id;?>bug->priList, $bug->pri, $bug->pri)?>title?> + + + bug->statusList, $bug->status);?> + +
+
diff --git a/module/block/view/buildblock.html.php b/module/block/view/buildblock.html.php index 520cb61b87..4d8cdf916f 100644 --- a/module/block/view/buildblock.html.php +++ b/module/block/view/buildblock.html.php @@ -10,28 +10,29 @@ * @link http://www.ranzhi.org */ ?> - - - - - - - - - - - get->entry}'" : ''; - $viewLink = $this->createLink('build', 'view', "buildID={$build->id}"); - ?> - > - - - - - - -
idAB?> build->product;?> build->name;?>build->date;?>
id;?>productName?>name?>date?>
- +
+ + + + + + + + + + + + get->entry}'" : ''; + $viewLink = $this->createLink('build', 'view', "buildID={$build->id}"); + ?> + > + + + + + + + +
idAB?> build->product;?> build->name;?>build->date;?>
id;?>productName?>name?>date?>
+
diff --git a/module/block/view/caseblock.html.php b/module/block/view/caseblock.html.php index b19e9cf3b2..e7a5e9a6a5 100644 --- a/module/block/view/caseblock.html.php +++ b/module/block/view/caseblock.html.php @@ -10,32 +10,56 @@ * @link http://www.ranzhi.org */ ?> - - - - - - - - - - - - - get->entry}'" : ''; - $viewLink = $this->createLink('testcase', 'view', "caseID={$case->id}"); - ?> - > - - - - - - - - -
idAB?>priAB?> case->title;?> testtask->lastRunTime;?> testtask->lastRunResult;?>statusAB;?>
id;?>case->priList, $case->pri, $case->pri)?>title?>lastRunDate)) echo date(DT_MONTHTIME1, strtotime($case->lastRunDate));?>lastRunResult) echo $lang->testcase->resultList[$case->lastRunResult];?>testcase->statusList[$case->status];?>
- +
+ + '> + + + + + + + + + + + + + + + + + get->entry}'" : ''; + $viewLink = $this->createLink('testcase', 'view', "caseID={$case->id}"); + ?> + > + + + + + + + + + + + + + +
idAB?>priAB?>case->title;?> testtask->lastRunTime;?> testtask->lastRunResult;?>statusAB;?>
id;?>case->priList, $case->pri, $case->pri)?>title?>lastRunDate)) echo date(DT_MONTHTIME1, strtotime($case->lastRunDate));?>lastRunResult) echo $lang->testcase->resultList[$case->lastRunResult];?> + + + testcase->statusList, $case->status);?> + +
+
diff --git a/module/block/view/dashboard.html.php b/module/block/view/dashboard.html.php index 7e491e96b8..8d472a632b 100644 --- a/module/block/view/dashboard.html.php +++ b/module/block/view/dashboard.html.php @@ -18,45 +18,87 @@ $useGuest = $this->app->user->account == 'guest'; ?>
- -
- - -
- $block):?> - block->closed) and strpos(",{$config->block->closed},", ",{$block->source}|{$block->block},") !== false) continue;?> -
-
params->color;?>' id='blockid?>' data-id='id?>' data-name='title?>' data-url='blockLink?>' height) echo "data-height='$block->height'";?>> -
-
- moreLink)):?> - moreLink, " ", null, "class='panel-action drag-disabled panel-action-more'"); ?> - - getExtViewFile(__FILE__)){include $extView; return helper::cd();}?> - \ No newline at end of file + diff --git a/module/block/view/dynamic.html.php b/module/block/view/dynamic.html.php index 6e85881708..d2d0eff58d 100644 --- a/module/block/view/dynamic.html.php +++ b/module/block/view/dynamic.html.php @@ -1,12 +1,17 @@ - - actor]) ? $users[$action->actor] : $action->actor; - if($action->action == 'login' or $action->action == 'logout' or empty($action->objectLink)) $action->objectName = $action->objectLabel = ''; - echo ""; - } - ?> -
"; - printf($lang->block->dynamicInfo, $action->date, $user, $action->actionLabel, $action->objectLabel, $action->objectLink, $action->objectName); - echo "
+
+
    + actor]) ? $users[$action->actor] : $action->actor; + if($action->action == 'login' or $action->action == 'logout' or empty($action->objectLink)) $action->objectName = $action->objectLabel = ''; + $class = $i % 3 == 0 ? "class='active'" : ''; + echo "
  • "; + printf($lang->block->dynamicInfo, $action->date, $user, $action->actionLabel, $action->objectLabel, $action->objectLink, $action->objectName); + echo "
  • "; + $i++; + } + ?> +
+
diff --git a/module/block/view/flowchart.html.php b/module/block/view/flowchart.html.php index 51e9d9976e..934414cee4 100644 --- a/module/block/view/flowchart.html.php +++ b/module/block/view/flowchart.html.php @@ -1,43 +1,26 @@ -
-block->flowchart as $flow):?> - -
- -
- -
- -
- + + + + + + + + + + + + + + block->flowchart as $flowchart):?> + + + + + + + + + + + +
block->lblFlowchart?>
diff --git a/module/block/view/planblock.html.php b/module/block/view/planblock.html.php index 5d5a56c8b4..f7ef59f194 100644 --- a/module/block/view/planblock.html.php +++ b/module/block/view/planblock.html.php @@ -10,30 +10,31 @@ * @link http://www.ranzhi.org */ ?> - - - - - - - - - - - - get->entry}'" : ''; - $viewLink = $this->createLink('productplan', 'view', "planID={$plan->id}"); - ?> - > - - - - - - - -
idAB?> productplan->product;?> productplan->title;?>productplan->begin;?>productplan->end;?>
id;?>productName?>title?>begin?>end?>
- +
+ + + + + + + + + + + + + get->entry}'" : ''; + $viewLink = $this->createLink('productplan', 'view', "planID={$plan->id}"); + ?> + > + + + + + + + + +
idAB?> productplan->product;?> productplan->title;?>productplan->begin;?>productplan->end;?>
id;?>productName?>title?>begin?>end?>
+
diff --git a/module/block/view/printassigntomeblock.html.php b/module/block/view/printassigntomeblock.html.php new file mode 100644 index 0000000000..a320f0fdb4 --- /dev/null +++ b/module/block/view/printassigntomeblock.html.php @@ -0,0 +1,35 @@ + + * @package block + * @version $Id$ + * @link http://www.zentao.net + */ +?> +
+ $bool):?> +
+ +
+ +
+ diff --git a/module/block/view/productblock.html.php b/module/block/view/productblock.html.php index 09386e9293..3e8661b5e4 100644 --- a/module/block/view/productblock.html.php +++ b/module/block/view/productblock.html.php @@ -10,38 +10,37 @@ * @link http://www.zentao.net */ ?> - - - - - - - - - - - - - - - - get->entry}'" : "class='text-center'"; - $viewLink = $this->createLink('product', 'browse', 'productID=' . $product->id); - ?> - > - - - - - - - - - - - -
product->name;?>story->statusList['active'];?>story->statusList['changed'];?>story->statusList['draft'];?>product->plans;?>product->releases;?>product->bugs;?>bug->unResolved;?>
name?>stories['active']?>stories['changed']?>stories['draft']?>plans?>releases?>bugs?>unResolved?>
- +
+ + + + + + + + + + + + + + + + get->entry}'" : ""; + $viewLink = $this->createLink('product', 'browse', 'productID=' . $product->id); + ?> + > + + + + + + + + + + + +
product->name;?>product->plans;?>product->releases;?>product->currentProject;?>story->statusList['active'];?>bug->unResolved;?>
name?>plans?>releases?>id, '');?>stories['active']?>unResolved?>
+
diff --git a/module/block/view/projectblock.html.php b/module/block/view/projectblock.html.php index e6858c71e0..b1f7597733 100644 --- a/module/block/view/projectblock.html.php +++ b/module/block/view/projectblock.html.php @@ -10,21 +10,22 @@ * @link http://www.zentao.net */ ?> -config->webRoot . 'js/';?> - - -
- +
+
- - - - - - - - + + + + + + + + + + + + @@ -35,57 +36,32 @@ $viewLink = $this->createLink('project', 'task', 'project=' . $project->id); ?> > - - - delay)):?> - - - - - - - - + + + - + + + + + + + +
project->name;?>project->end;?>statusAB;?>project->totalEstimate;?>project->totalConsumed;?>project->totalLeft;?>project->progress;?>project->burn;?>project->name;?>project->end;?>statusAB;?>project->totalEstimate;?>project->totalConsumed;?>project->totalLeft;?>project->progress;?>project->burn;?>
createLink('project', 'task', 'project=' . $project->id), $project->name, '', "title='$project->name'");?>end;?>project->delayed;?>project->statusList[$project->status];?>hours->totalEstimate;?>hours->totalConsumed;?>hours->totalLeft;?> - - hours->progress;?>% + createLink('project', 'task', 'project=' . $project->id), $project->name, '', "title='$project->name'");?>end;?> + delay)):?> + project->delayed;?> + + project->statusList[$project->status];?> + burns);?>'>hours->totalEstimate;?>hours->totalConsumed;?>hours->totalLeft;?> +
+
+ hours->progress;?>% +
+
+
burns);?>'>
- diff --git a/module/block/view/publicform.html.php b/module/block/view/publicform.html.php index 1750271339..333f079bfd 100644 --- a/module/block/view/publicform.html.php +++ b/module/block/view/publicform.html.php @@ -10,17 +10,16 @@ * @link http://www.zentao.net */ ?> - - block->name?> - title : '', "class='form-control' autocomplete='off'")?> - - - block->style;?> - -
+
+ +
title : '', "class='form-control' autocomplete='off'")?>
+
+
+ +
block->grid;?> - block->gridOptions, $block ? $block->grid : 4, "class='form-control'")?> + block->gridOptions, $block ? $block->grid : 8, "class='form-control chosen'")?>
params->color) ? 'btn-' . $block->params->color : 'btn-default'?>
-
- - +
+
diff --git a/module/block/view/releaseblock.html.php b/module/block/view/releaseblock.html.php index d26e1e478d..f3e089cc49 100644 --- a/module/block/view/releaseblock.html.php +++ b/module/block/view/releaseblock.html.php @@ -10,32 +10,33 @@ * @link http://www.ranzhi.org */ ?> - - - - - - - - - - - - - get->entry}'" : ''; - $viewLink = $this->createLink('release', 'view', "releaseID={$release->id}"); - ?> - > - - - - - - - - -
idAB?> release->product;?> release->name;?> release->build;?>release->date;?>release->status;?>
id;?>productName?>name?>buildName?>date?>release->statusList[$release->status]?>
- +
+ + + + + + + + + + + + + + get->entry}'" : ''; + $viewLink = $this->createLink('release', 'view', "releaseID={$release->id}"); + ?> + > + + + + + + + + + +
idAB?> release->product;?> release->name;?> release->build;?>release->date;?>release->status;?>
id;?>productName?>name?>buildName?>date?>release->statusList[$release->status]?>
+
diff --git a/module/block/view/set.html.php b/module/block/view/set.html.php index ca3295ec99..4ba840919a 100644 --- a/module/block/view/set.html.php +++ b/module/block/view/set.html.php @@ -11,7 +11,7 @@ */ ?> block->moduleList[$source])) +if(!empty($params)) { include 'setmodule.html.php'; die(); @@ -24,20 +24,14 @@ if($type == 'html') include '../../common/view/kindeditor.html.php'; } ?> -
'> - - - - - - - - - - - -
block->lblHtml;?>params->html : '', "class='form-control' rows='10'")?>
-
+ +createLink('block', 'set', "id=$id&type=$type&source=$source"));?> + +
+ +
params->html : '', "class='form-control' rows='10'")?>
+
+ +
+ '> + + + + + + + + + + + + + + + + + get->entry}'" : ''; + $viewLink = $this->createLink('story', 'view', "storyID={$story->id}"); + ?> + > + + story->priList, $story->pri, $story->pri);?> + + + + + + + + + + + + +
idAB?>priAB?>story->title;?>story->estimateAB;?>statusAB;?>story->stageAB;?>
id;?>title?>estimate?> + + story->statusList, $story->status);?> + + + + story->stageList, $story->stage, $story->stage);?> + +
+
diff --git a/module/block/view/taskblock.html.php b/module/block/view/taskblock.html.php index 3ab4b05f0b..38104dd9ec 100644 --- a/module/block/view/taskblock.html.php +++ b/module/block/view/taskblock.html.php @@ -10,35 +10,42 @@ * @link http://www.ranzhi.org */ ?> - - - - - - - - - - - - - - get->entry}'" : ''; - $viewLink = $this->createLink('task', 'view', "taskID={$task->id}"); - ?> - > - - - - - - - -
idAB?>priAB?> task->name;?>task->estimateAB;?>task->deadline;?>statusAB;?>
id;?>task->priList, $task->pri, $task->pri)?>name?>estimate?>'>deadline, 0, 4) > 0) echo $task->deadline;?>task->statusList, $task->status, $task->status);?> -
- +
+ '> + + + + + + + + + + + + + + + get->entry}'" : ''; + $viewLink = $this->createLink('task', 'view', "taskID={$task->id}"); + ?> + > + + + + + + + + + + + +
idAB?>priAB?> task->name;?>task->estimateAB;?>task->deadline;?>statusAB;?>
id;?>task->priList, $task->pri, $task->pri)?>name?>estimate?>deadline, 0, 4) > 0) echo $task->deadline;?> + + + task->statusList, $task->status);?> + +
+
diff --git a/module/block/view/testtaskblock.html.php b/module/block/view/testtaskblock.html.php index 90b8a2a2ad..896c450e46 100644 --- a/module/block/view/testtaskblock.html.php +++ b/module/block/view/testtaskblock.html.php @@ -10,32 +10,33 @@ * @link http://www.ranzhi.org */ ?> - - - - - - - - - - - - - get->entry}'" : ''; - $viewLink = $this->createLink('testtask', 'view', "testtaskID={$testtask->id}"); - ?> - > - - - - - - - - -
idAB?> testtask->product;?> testtask->name;?> testtask->project . '/' . $lang->testtask->build;?>testtask->begin;?>testtask->end;?>
id;?>productName?>name?>buildName?>'>projectName . '/' . $testtask->buildName?>begin?>end?>
- +
+ + + + + + + + + + + + + + get->entry}'" : ''; + $viewLink = $this->createLink('testtask', 'view', "testtaskID={$testtask->id}"); + ?> + > + + + + + + + + + +
idAB?>testtask->product;?> testtask->name;?>testtask->project . '/' . $lang->testtask->build;?>testtask->begin;?>testtask->end;?>
id;?>productName?>name?>buildName?>'>projectName . '/' . $testtask->buildName?>begin?>end?>
+
diff --git a/module/block/view/todoblock.html.php b/module/block/view/todoblock.html.php index 1bb55b5a37..e508e91628 100644 --- a/module/block/view/todoblock.html.php +++ b/module/block/view/todoblock.html.php @@ -10,30 +10,115 @@ * @link http://www.ranzhi.org */ ?> - - - - - - - - - - - $todo):?> - get->entry}'" : ''; - $viewLink = $this->createLink('todo', 'view', "todoID={$todo->id}&from=my"); - ?> - > - - - - - - - -
todo->date?>priAB?> todo->name;?>todo->beginAB;?>todo->endAB;?>
date == '2030-01-01' ? $lang->todo->periods['future'] : $todo->date;?>todo->priList, $todo->pri, $todo->pri)?>name?>begin?>end?>
- +
+
+
+
+
'> +

todo->create . $lang->todo->common;?>

+
+
+
+
+ +
todo->priList, '', "class='form-control chosen'");?>
+
+
+ +
+
+ + +
+
+
+
+ +
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ + save, "onclick='ajaxCreateTodo(this)'", "btn btn-primary btn-wide");?> + +
+
+
+
+ +
+ +
diff --git a/module/block/view/welcome.html.php b/module/block/view/welcome.html.php new file mode 100644 index 0000000000..73333c6b8e --- /dev/null +++ b/module/block/view/welcome.html.php @@ -0,0 +1,71 @@ + + * @package block + * @version $Id$ + * @link http://www.zentao.net + */ +?> +
+
+
+

block->welcomeList[$welcomeType], $app->user->realname)?>

+
    + tutorial->tasks as $taskKey => $task) + { + if($i > 3) break; + $class = strpos(",$tutorialed,", ",$taskKey,") !== false ? "class='active'" : ''; + echo "
  • " . html::a($this->createLink('tutorial', 'index', "referer=&task=$taskKey"), $i . '. ' . $task['title']) . "
  • "; + $i++; + } + ?> +
+
+
+

block->leftToday?>

+
+
+
block->myTask?>
+
+ +
+ block->delayed . ' ' . $delay['task']?> +
+ +
+
+
block->myBug?>
+
+ +
+ block->delayed . ' ' . $delay['bug']?> +
+ +
+
+
block->myStory?>
+
+
+
+
block->myProject?>
+
+ +
+ block->delayed . ' ' . $delay['project']?> +
+ +
+
+
block->myProduct?>
+
+
+
+
+
+
diff --git a/module/bug/config.php b/module/bug/config.php index 190b518f2d..6ac9bc0717 100644 --- a/module/bug/config.php +++ b/module/bug/config.php @@ -267,7 +267,7 @@ $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['assignedTo']['title'] = 'assignedTo'; +$config->bug->datatable->fieldList['assignedTo']['title'] = 'assignedToAB'; $config->bug->datatable->fieldList['assignedTo']['fixed'] = 'no'; $config->bug->datatable->fieldList['assignedTo']['width'] = '80'; $config->bug->datatable->fieldList['assignedTo']['required'] = 'no'; diff --git a/module/bug/control.php b/module/bug/control.php index 7abd9c2b1c..aecb04362d 100644 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -179,7 +179,7 @@ class bug extends control * @access public * @return void */ - public function report($productID, $browseType, $branchID, $moduleID) + public function report($productID, $browseType, $branchID, $moduleID, $chartType = '') { $this->loadModel('report'); $this->view->charts = array(); @@ -191,6 +191,7 @@ class bug extends control $chartFunc = 'getDataOf' . $chart; $chartData = $this->bug->$chartFunc(); $chartOption = $this->lang->bug->report->$chart; + if(!empty($chartType)) $chartOption->type = $chartType; $this->bug->mergeChartOption($chart); $this->view->charts[$chart] = $chartOption; @@ -204,7 +205,9 @@ class bug extends control $this->view->position[] = $this->lang->bug->reportChart; $this->view->productID = $productID; $this->view->browseType = $browseType; + $this->view->branchID = $branchID; $this->view->moduleID = $moduleID; + $this->view->chartType = $chartType; $this->view->checkedCharts = $this->post->charts ? join(',', $this->post->charts) : ''; $this->display(); } @@ -245,7 +248,14 @@ class bug extends control } $actionID = $this->action->create('bug', $bugID, 'Opened'); - $this->bug->sendmail($bugID, $actionID); + + $extras = str_replace(array(',', ' '), array('&', ''), $extras); + parse_str($extras, $output); + if(isset($output['todoID'])) + { + $this->dao->update(TABLE_TODO)->set('status')->eq('done')->where('id')->eq($output['todoID'])->exec(); + $this->action->create('todo', $output['todoID'], 'finished', '', "BUG:$bugID"); + } $location = $this->createLink('bug', 'browse', "productID={$this->post->product}&branch=$branch&type=byModule¶m={$this->post->module}"); $response['locate'] = isset($_SESSION['bugList']) ? $this->session->bugList : $location; @@ -304,6 +314,13 @@ class bug extends control $deadline = $bug->deadline; $color = $bug->color; } + if(isset($todoID)) + { + $todo = $this->loadModel('todo')->getById($todoID); + $title = $todo->name; + $steps = $todo->desc; + $pri = $todo->pri; + } /* If projectID is setted, get builds and stories of this project. */ if($projectID) @@ -388,7 +405,6 @@ class bug extends control if(!empty($_POST)) { $actions = $this->bug->batchCreate($productID, $branch); - foreach($actions as $bugID => $actionID) $this->bug->sendmail($bugID, $actionID); die(js::locate($this->session->bugList, 'parent')); } @@ -530,7 +546,6 @@ class bug extends control if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ; $actionID = $this->action->create('bug', $bugID, $action, $fileAction . $this->post->comment); $this->action->logHistory($actionID, $changes); - $this->bug->sendmail($bugID, $actionID); } $bug = $this->bug->getById($bugID); @@ -625,7 +640,6 @@ class bug extends control $actionID = $this->action->create('bug', $bugID, 'Edited'); $this->action->logHistory($actionID, $changes); - $this->bug->sendmail($bugID, $actionID); $bug = $this->bug->getById($bugID); if($bug->toTask != 0) @@ -750,7 +764,6 @@ class bug extends control if(dao::isError()) die(js::error(dao::getError())); $actionID = $this->action->create('bug', $bugID, 'Assigned', $this->post->comment, $this->post->assignedTo); $this->action->logHistory($actionID, $changes); - $this->bug->sendmail($bugID, $actionID); if(isonlybody()) die(js::closeModal('parent.parent')); die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); @@ -787,7 +800,6 @@ class bug extends control $this->loadModel('action'); $actionID = $this->action->create('bug', $bugID, 'Edited'); $this->action->logHistory($actionID, $changes); - $this->bug->sendmail($bugID, $actionID); } } $this->loadModel('score')->create('ajax', 'batchOther'); @@ -815,7 +827,6 @@ class bug extends control $this->loadModel('action'); $actionID = $this->action->create('bug', $bugID, 'Edited'); $this->action->logHistory($actionID, $changes); - $this->bug->sendmail($bugID, $actionID); } } $this->loadModel('score')->create('ajax', 'batchOther'); @@ -843,11 +854,10 @@ class bug extends control if(dao::isError()) die(js::error(dao::getError())); $actionID = $this->action->create('bug', $bugID, 'Assigned', $this->post->comment, $this->post->assignedTo); $this->action->logHistory($actionID, $changes); - $this->bug->sendmail($bugID, $actionID); } $this->loadModel('score')->create('ajax', 'batchOther'); } - if($type == 'product') die(js::locate($this->createLink('bug', 'browse', "productID=$projectID"))); + if($type == 'product') die(js::locate($this->createLink('bug', 'browse', "productID=$projectID"), 'parent')); if($type == 'my') die(js::locate($this->createLink('my', 'bug'))); die(js::locate($this->createLink('project', 'bug', "projectID=$projectID"))); } @@ -867,7 +877,6 @@ class bug extends control if(dao::isError()) die(js::error(dao::getError())); $actionID = $this->action->create('bug', $bugID, 'bugConfirmed', $this->post->comment); $this->action->logHistory($actionID, $changes); - $this->bug->sendmail($bugID, $actionID); if(isonlybody()) die(js::closeModal('parent.parent')); die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); } @@ -898,11 +907,7 @@ class bug extends control $bugIDList = array_unique($bugIDList); $this->bug->batchConfirm($bugIDList); if(dao::isError()) die(js::error(dao::getError())); - foreach($bugIDList as $bugID) - { - $actionID = $this->action->create('bug', $bugID, 'bugConfirmed'); - $this->bug->sendmail($bugID, $actionID); - } + foreach($bugIDList as $bugID) $this->action->create('bug', $bugID, 'bugConfirmed'); $this->loadModel('score')->create('ajax', 'batchOther'); die(js::locate($this->session->bugList, 'parent')); } @@ -924,7 +929,6 @@ class bug extends control $fileAction = !empty($files) ? $this->lang->addFiles . join(',', $files) . "\n" : ''; $actionID = $this->action->create('bug', $bugID, 'Resolved', $fileAction . $this->post->comment, $this->post->resolution . ($this->post->duplicateBug ? ':' . (int)$this->post->duplicateBug : '')); - $this->bug->sendmail($bugID, $actionID); $bug = $this->bug->getById($bugID); if($bug->toTask != 0) @@ -960,7 +964,7 @@ class bug extends control $this->view->users = $users; $this->view->assignedTo = $assignedTo; $this->view->projects = $this->loadModel('product')->getProjectPairs($productID, $bug->branch ? "0,{$bug->branch}" : 0, $params = 'nodeleted'); - $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID, $branch = 0, 'all', true , $bug->project); + $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID, $branch = 0, 'all'); $this->view->actions = $this->action->getList('bug', $bugID); $this->display(); } @@ -979,11 +983,7 @@ class bug extends control $bugIDList = array_unique($bugIDList); $bugIDList = $this->bug->batchResolve($bugIDList, $resolution, $resolvedBuild); if(dao::isError()) die(js::error(dao::getError())); - foreach($bugIDList as $bugID) - { - $actionID = $this->action->create('bug', $bugID, 'Resolved', '', $resolution); - $this->bug->sendmail($bugID, $actionID); - } + foreach($bugIDList as $bugID) $this->action->create('bug', $bugID, 'Resolved', '', $resolution); $this->loadModel('score')->create('ajax', 'batchOther'); die(js::locate($this->session->bugList, 'parent')); } @@ -1002,8 +1002,7 @@ class bug extends control $this->bug->activate($bugID); if(dao::isError()) die(js::error(dao::getError())); $files = $this->loadModel('file')->saveUpload('bug', $bugID); - $actionID = $this->action->create('bug', $bugID, 'Activated', $this->post->comment); - $this->bug->sendmail($bugID, $actionID); + $this->action->create('bug', $bugID, 'Activated', $this->post->comment); if(isonlybody()) die(js::closeModal('parent.parent')); die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); } @@ -1018,7 +1017,7 @@ class bug extends control $this->view->bug = $bug; $this->view->users = $this->user->getPairs('nodeleted', $bug->resolvedBy); - $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID, $bug->branch, 'noempty', true, $bug->project); + $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID, $bug->branch, 'noempty'); $this->view->actions = $this->action->getList('bug', $bugID); $this->display(); @@ -1037,8 +1036,7 @@ class bug extends control { $this->bug->close($bugID); if(dao::isError()) die(js::error(dao::getError())); - $actionID = $this->action->create('bug', $bugID, 'Closed', $this->post->comment); - $this->bug->sendmail($bugID, $actionID); + $this->action->create('bug', $bugID, 'Closed', $this->post->comment); if(isonlybody()) die(js::closeModal('parent.parent')); die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); } @@ -1170,8 +1168,7 @@ class bug extends control $this->bug->close($bugID); - $actionID = $this->action->create('bug', $bugID, 'Closed'); - $this->bug->sendmail($bugID, $actionID); + $this->action->create('bug', $bugID, 'Closed'); } $this->loadModel('score')->create('ajax', 'batchOther'); if(isset($skipBugs)) echo js::alert(sprintf($this->lang->bug->skipClose, join(',', $skipBugs))); @@ -1190,11 +1187,7 @@ class bug extends control if($this->post->statusList) { $activateBugs = $this->bug->batchActivate(); - foreach($activateBugs as $bugID => $bug) - { - $actionID = $this->action->create('bug', $bugID, 'Activated', $bug['comment']); - $this->bug->sendmail($bugID, $actionID); - } + foreach($activateBugs as $bugID => $bug) $this->action->create('bug', $bugID, 'Activated', $bug['comment']); $this->loadModel('score')->create('ajax', 'batchOther'); die(js::locate($this->session->bugList, 'parent')); } diff --git a/module/bug/js/create.js b/module/bug/js/create.js index f44d38b6df..0b407a1f5e 100644 --- a/module/bug/js/create.js +++ b/module/bug/js/create.js @@ -123,7 +123,7 @@ $(function() { var $group = $('#bugTypeInputGroup'); var width = $group.width(), addonWidth = 0; - var $controls = $group.children('.form-control'); + var $controls = $group.find('.chosen-single'); $group.children('.input-group-addon').each(function() { addonWidth += $(this).outerWidth(); diff --git a/module/bug/js/report.js b/module/bug/js/report.js index 38276947f3..5c00682a61 100644 --- a/module/bug/js/report.js +++ b/module/bug/js/report.js @@ -12,3 +12,9 @@ $(function() fixedTableHead('.table-wrapper'); $(window).resize(resizeChartTable); }); + +function changeChartType(type) +{ + $('form').attr('action', createLink('bug', 'report', 'productID=' + productID + '&browseType=' + browseType + '&branchID=' + branchID + '&moduleID=' + moduleID + '&chartType=' + type)); + $('form').find('#submit').click(); +} diff --git a/module/bug/lang/en.php b/module/bug/lang/en.php index dad314be53..d11e141768 100644 --- a/module/bug/lang/en.php +++ b/module/bug/lang/en.php @@ -21,9 +21,9 @@ $lang->bug->project = $lang->projectCommon; $lang->bug->story = 'Story'; $lang->bug->task = 'Task'; $lang->bug->title = 'Title'; -$lang->bug->severity = 'Severity'; +$lang->bug->severity = 'Severity(S)'; $lang->bug->severityAB = 'S'; -$lang->bug->pri = 'Priority'; +$lang->bug->pri = 'Priority(P)'; $lang->bug->type = 'Type'; $lang->bug->os = 'OS'; $lang->bug->browser = 'Browser'; @@ -37,26 +37,28 @@ $lang->bug->confirmed = 'Confirmed'; $lang->bug->toTask = 'Convert to Task'; $lang->bug->toStory = 'Convert to Story'; $lang->bug->mailto = 'Mail To'; -$lang->bug->openedBy = 'Open By'; -$lang->bug->openedDate = 'Open On'; -$lang->bug->openedDateAB = 'Created on'; +$lang->bug->openedBy = 'Creator'; +$lang->bug->openedDate = 'Created on'; +$lang->bug->openedDateAB = 'Created'; $lang->bug->openedBuild = 'Open Build'; -$lang->bug->assignedTo = 'Assigned To'; +$lang->bug->assignedTo = 'To'; +$lang->bug->assignBug = 'Assign To'; +$lang->bug->assignedToAB = 'To'; $lang->bug->assignedDate = 'Assigned On'; -$lang->bug->resolvedBy = 'Resolved By'; +$lang->bug->resolvedBy = 'Resolved'; $lang->bug->resolvedByAB = 'Resolved'; $lang->bug->resolution = 'Solution'; $lang->bug->resolutionAB = 'Solution'; $lang->bug->resolvedBuild = 'Resolved Build'; -$lang->bug->resolvedDate = 'Resolved On'; -$lang->bug->resolvedDateAB = 'Resolved On'; +$lang->bug->resolvedDate = 'Resolved on'; +$lang->bug->resolvedDateAB = 'Resolved'; $lang->bug->deadline = 'Deadline'; $lang->bug->plan = 'Plan'; $lang->bug->closedBy = 'Closed By'; $lang->bug->closedDate = 'Closed On'; $lang->bug->duplicateBug = 'Duplicate'; -$lang->bug->lastEditedBy = 'Last Edited By'; -$lang->bug->linkBug = 'linked'; +$lang->bug->lastEditedBy = 'Edited By'; +$lang->bug->linkBug = 'Linked Bug'; $lang->bug->linkBugs = 'Link Bug'; $lang->bug->unlinkBug = 'Unlink'; $lang->bug->case = 'Case'; @@ -77,7 +79,8 @@ $lang->bug->confirmBug = 'Confirm'; $lang->bug->batchConfirm = 'Batch Confirm'; $lang->bug->edit = 'Edit'; $lang->bug->batchEdit = 'Batch Edit'; -$lang->bug->batchChangeModule = 'Batch Modify'; +$lang->bug->batchChangeModule = 'Batch Modify Module'; +$lang->bug->batchChangeBranch = 'Batch Modify Branch'; $lang->bug->batchClose = 'Batch Close'; $lang->bug->assignTo = 'Assign'; $lang->bug->batchAssignTo = 'Batch Assign'; @@ -87,35 +90,40 @@ $lang->bug->resolve = 'Resolve'; $lang->bug->batchResolve = 'Batch Resolve'; $lang->bug->close = 'Close'; $lang->bug->activate = 'Activate'; -$lang->bug->batchActivate = 'batchActivate'; +$lang->bug->batchActivate = 'Batch Activate'; $lang->bug->reportChart = 'Report'; $lang->bug->export = 'Export'; $lang->bug->delete = 'Delete'; $lang->bug->deleted = 'Deleted'; $lang->bug->saveTemplate = 'Save as Template'; -$lang->bug->setPublic = 'Set as Public'; +$lang->bug->setPublic = 'Set as Public Template'; $lang->bug->deleteTemplate = 'Delete Template'; $lang->bug->confirmStoryChange = 'Confirm Story Change'; $lang->bug->copy = 'Copy'; /* 查询条件列表。*/ -$lang->bug->assignToMe = 'Assigned to Me'; -$lang->bug->openedByMe = 'Created by Me'; -$lang->bug->resolvedByMe = 'Resolved by Me'; -$lang->bug->closedByMe = 'Closed by Me'; +$lang->bug->assignToMe = 'AssignedToMe'; +$lang->bug->openedByMe = 'CreatedByMe'; +$lang->bug->resolvedByMe = 'ResolvedByMe'; +$lang->bug->closedByMe = 'ClosedByMe'; $lang->bug->assignToNull = 'Unassigned'; $lang->bug->unResolved = 'Unresolved'; -$lang->bug->toClosed = 'To Be Closed'; -$lang->bug->unclosed = 'Open'; +$lang->bug->toClosed = 'WaitForClose'; +$lang->bug->unclosed = 'Active'; +$lang->bug->unconfirmed = 'UnConfirmed'; $lang->bug->longLifeBugs = 'Pending'; $lang->bug->postponedBugs = 'Postponed'; $lang->bug->overdueBugs = 'Overdue'; $lang->bug->allBugs = 'All'; $lang->bug->byQuery = 'Search'; -$lang->bug->needConfirm = 'Story Change'; +$lang->bug->needConfirm = 'StoryChanged'; $lang->bug->allProduct = 'All' . $lang->productCommon; $lang->bug->my = 'My'; +$lang->bug->assignToMeAB = 'Assigned To Me'; +$lang->bug->openedByMeAB = 'Created By Me'; +$lang->bug->resolvedByMeAB = 'Resolved By Me'; + $lang->bug->ditto = 'Ditto'; $lang->bug->dittoNotice = 'This bug is not linked to the same product as the last one!'; @@ -136,7 +144,7 @@ $lang->bug->lblTypeAndSeverity = 'Type/Priority Level'; $lang->bug->lblSystemBrowserAndHardware = 'System/Browser'; $lang->bug->legendSteps = 'Repro Steps'; $lang->bug->legendComment = 'Note'; -$lang->bug->legendLife = 'Lifecycle'; +$lang->bug->legendLife = 'Life of Bug'; $lang->bug->legendMisc = 'Misc'; $lang->bug->legendRelated = 'Related Info'; @@ -216,7 +224,7 @@ $lang->bug->browserList['other'] = 'Other'; $lang->bug->typeList[''] = ''; $lang->bug->typeList['codeerror'] = 'Code Error'; -$lang->bug->typeList['interface'] = 'Interface Optimization'; +$lang->bug->typeList['interface'] = 'UI Optimization'; $lang->bug->typeList['config'] = 'Configuration'; $lang->bug->typeList['install'] = 'Install/Deploy'; $lang->bug->typeList['security'] = 'Security'; @@ -238,22 +246,22 @@ $lang->bug->confirmedList[1] = 'Yes'; $lang->bug->confirmedList[0] = 'No'; $lang->bug->resolutionList[''] = ''; -$lang->bug->resolutionList['bydesign'] = 'Design Issue'; +$lang->bug->resolutionList['bydesign'] = 'By Design'; $lang->bug->resolutionList['duplicate'] = 'Duplicated'; $lang->bug->resolutionList['external'] = 'External'; $lang->bug->resolutionList['fixed'] = 'Resolved'; $lang->bug->resolutionList['notrepro'] = 'Irreproducible'; $lang->bug->resolutionList['postponed'] = 'Postponed'; $lang->bug->resolutionList['willnotfix'] = "Not to Resolve"; -$lang->bug->resolutionList['tostory'] = 'Convert to Story'; +$lang->bug->resolutionList['tostory'] = 'Converted to Story'; /* 统计报表。*/ $lang->bug->report = new stdclass(); $lang->bug->report->common = 'Report'; $lang->bug->report->select = 'Select Report Type '; -$lang->bug->report->create = 'Generate a Report'; +$lang->bug->report->create = 'Generate Report'; -$lang->bug->report->charts['bugsPerProject'] = $lang->projectCommon . 'Bugs'; +$lang->bug->report->charts['bugsPerProject'] = $lang->projectCommon . ' Bugs'; $lang->bug->report->charts['bugsPerBuild'] = 'Bugs Per Build'; $lang->bug->report->charts['bugsPerModule'] = 'Bugs Per Module'; $lang->bug->report->charts['openedBugsPerDay'] = 'Reported Bugs Per Day'; @@ -361,14 +369,17 @@ $lang->bug->placeholder = new stdclass(); $lang->bug->placeholder->chooseBuilds = 'Choose Build...'; $lang->bug->placeholder->newBuildName = 'The name of new build'; -$lang->bug->mySelects['assigntome'] = $lang->bug->assignToMe; -$lang->bug->mySelects['openedbyme'] = $lang->bug->openedByMe; -$lang->bug->mySelects['resolvedbyme'] = $lang->bug->resolvedByMe; +$lang->bug->mySelects['assigntome'] = $lang->bug->assignToMeAB; +$lang->bug->mySelects['openedbyme'] = $lang->bug->openedByMeAB; +$lang->bug->mySelects['resolvedbyme'] = $lang->bug->resolvedByMeAB; $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed; $lang->bug->featureBar['browse']['all'] = $lang->bug->allBugs; + + + $lang->bug->featureBar['browse']['my'] = $lang->bug->my; -$lang->bug->featureBar['browse']['unconfirmed'] = $lang->bug->confirmedList[0]; +$lang->bug->featureBar['browse']['unconfirmed'] = $lang->bug->unconfirmed; $lang->bug->featureBar['browse']['assigntonull'] = $lang->bug->assignToNull; $lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved; $lang->bug->featureBar['browse']['toclosed'] = $lang->bug->toClosed; diff --git a/module/bug/lang/zh-cn.php b/module/bug/lang/zh-cn.php index 90b0fc7337..d04c8a23da 100644 --- a/module/bug/lang/zh-cn.php +++ b/module/bug/lang/zh-cn.php @@ -42,6 +42,8 @@ $lang->bug->openedDate = '创建日期'; $lang->bug->openedDateAB = '创建日期'; $lang->bug->openedBuild = '影响版本'; $lang->bug->assignedTo = '指派给'; +$lang->bug->assignBug = '指派给'; +$lang->bug->assignedToAB = '指派给'; $lang->bug->assignedDate = '指派日期'; $lang->bug->resolvedBy = '解决者'; $lang->bug->resolvedByAB = '解决'; @@ -78,6 +80,7 @@ $lang->bug->batchConfirm = '批量确认'; $lang->bug->edit = '编辑'; $lang->bug->batchEdit = '批量编辑'; $lang->bug->batchChangeModule = '批量修改模块'; +$lang->bug->batchChangeBranch = '批量修改分支'; $lang->bug->batchClose = '批量关闭'; $lang->bug->assignTo = '指派'; $lang->bug->batchAssignTo = '批量指派'; @@ -107,6 +110,7 @@ $lang->bug->assignToNull = '未指派'; $lang->bug->unResolved = '未解决'; $lang->bug->toClosed = '待关闭'; $lang->bug->unclosed = '未关闭'; +$lang->bug->unconfirmed = '未确认'; $lang->bug->longLifeBugs = '久未处理'; $lang->bug->postponedBugs = '被延期'; $lang->bug->overdueBugs = '过期Bug'; @@ -116,6 +120,10 @@ $lang->bug->needConfirm = '需求变动'; $lang->bug->allProduct = '所有' . $lang->productCommon; +$lang->bug->assignToMeAB = '指派给我'; +$lang->bug->openedByMeAB = '由我创建'; +$lang->bug->resolvedByMeAB = '由我解决'; + $lang->bug->ditto = '同上'; $lang->bug->dittoNotice = '该bug与上一bug不属于同一产品!'; @@ -154,8 +162,8 @@ $lang->bug->confirmDeleteTemplate = '您确认要删除该模板吗?'; /* 模板。*/ $lang->bug->tplStep = "

[步骤]

"; -$lang->bug->tplResult = "

[结果]

"; -$lang->bug->tplExpect = "

[期望]

"; +$lang->bug->tplResult = "

[结果]

"; +$lang->bug->tplExpect = "

[期望]

"; /* 各个字段取值列表。*/ $lang->bug->severityList[3] = '3'; @@ -361,12 +369,17 @@ $lang->bug->placeholder = new stdclass(); $lang->bug->placeholder->chooseBuilds = '选择相关版本...'; $lang->bug->placeholder->newBuildName = '新版本名称'; + + + + $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed; $lang->bug->featureBar['browse']['all'] = $lang->bug->allBugs; $lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe; $lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe; $lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe; -$lang->bug->featureBar['browse']['unconfirmed'] = $lang->bug->confirmedList[0]; + +$lang->bug->featureBar['browse']['unconfirmed'] = $lang->bug->unconfirmed; $lang->bug->featureBar['browse']['assigntonull'] = $lang->bug->assignToNull; $lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved; $lang->bug->featureBar['browse']['toclosed'] = $lang->bug->toClosed; diff --git a/module/bug/lang/zh-tw.php b/module/bug/lang/zh-tw.php index 0e144dc698..7051f98f04 100644 --- a/module/bug/lang/zh-tw.php +++ b/module/bug/lang/zh-tw.php @@ -42,6 +42,8 @@ $lang->bug->openedDate = '創建日期'; $lang->bug->openedDateAB = '創建日期'; $lang->bug->openedBuild = '影響版本'; $lang->bug->assignedTo = '指派給'; +$lang->bug->assignBug = '指派給'; +$lang->bug->assignedToAB = '指派給'; $lang->bug->assignedDate = '指派日期'; $lang->bug->resolvedBy = '解決者'; $lang->bug->resolvedByAB = '解決'; @@ -72,12 +74,13 @@ $lang->bug->colorTag = '顏色標籤'; /* 方法列表。*/ $lang->bug->index = '首頁'; $lang->bug->create = '提Bug'; -$lang->bug->batchCreate = '批量添加'; +$lang->bug->batchCreate = '批量提Bug'; $lang->bug->confirmBug = '確認'; $lang->bug->batchConfirm = '批量確認'; $lang->bug->edit = '編輯'; $lang->bug->batchEdit = '批量編輯'; $lang->bug->batchChangeModule = '批量修改模組'; +$lang->bug->batchChangeBranch = '批量修改分支'; $lang->bug->batchClose = '批量關閉'; $lang->bug->assignTo = '指派'; $lang->bug->batchAssignTo = '批量指派'; @@ -107,6 +110,7 @@ $lang->bug->assignToNull = '未指派'; $lang->bug->unResolved = '未解決'; $lang->bug->toClosed = '待關閉'; $lang->bug->unclosed = '未關閉'; +$lang->bug->unconfirmed = '未確認'; $lang->bug->longLifeBugs = '久未處理'; $lang->bug->postponedBugs = '被延期'; $lang->bug->overdueBugs = '過期Bug'; @@ -115,6 +119,11 @@ $lang->bug->byQuery = '搜索'; $lang->bug->needConfirm = '需求變動'; $lang->bug->allProduct = '所有' . $lang->productCommon; + +$lang->bug->assignToMeAB = '指派給我'; +$lang->bug->openedByMeAB = '由我創建'; +$lang->bug->resolvedByMeAB = '由我解決'; + $lang->bug->ditto = '同上'; $lang->bug->dittoNotice = '該bug與上一bug不屬於同一產品!'; @@ -153,8 +162,8 @@ $lang->bug->confirmDeleteTemplate = '您確認要刪除該模板嗎?'; /* 模板。*/ $lang->bug->tplStep = "

[步驟]

"; -$lang->bug->tplResult = "

[結果]

"; -$lang->bug->tplExpect = "

[期望]

"; +$lang->bug->tplResult = "

[結果]

"; +$lang->bug->tplExpect = "

[期望]

"; /* 各個欄位取值列表。*/ $lang->bug->severityList[3] = '3'; @@ -216,17 +225,17 @@ $lang->bug->browserList['other'] = '其他'; $lang->bug->typeList[''] = ''; $lang->bug->typeList['codeerror'] = '代碼錯誤'; $lang->bug->typeList['interface'] = '界面優化'; -$lang->bug->typeList['designchange'] = '設計變更'; -$lang->bug->typeList['newfeature'] = '新增需求'; -$lang->bug->typeList['designdefect'] = '設計缺陷'; $lang->bug->typeList['config'] = '配置相關'; $lang->bug->typeList['install'] = '安裝部署'; $lang->bug->typeList['security'] = '安全相關'; $lang->bug->typeList['performance'] = '性能問題'; $lang->bug->typeList['standard'] = '標準規範'; $lang->bug->typeList['automation'] = '測試腳本'; -$lang->bug->typeList['trackthings'] = '事務跟蹤'; $lang->bug->typeList['others'] = '其他'; +$lang->bug->typeList['designchange'] = '設計變更'; +$lang->bug->typeList['newfeature'] = '新增需求'; +$lang->bug->typeList['designdefect'] = '設計缺陷'; +$lang->bug->typeList['trackthings'] = '事務跟蹤'; $lang->bug->statusList[''] = ''; $lang->bug->statusList['active'] = '激活'; @@ -360,12 +369,17 @@ $lang->bug->placeholder = new stdclass(); $lang->bug->placeholder->chooseBuilds = '選擇相關版本...'; $lang->bug->placeholder->newBuildName = '新版本名稱'; + + + + $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed; $lang->bug->featureBar['browse']['all'] = $lang->bug->allBugs; $lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe; $lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe; $lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe; -$lang->bug->featureBar['browse']['unconfirmed'] = $lang->bug->confirmedList[0]; + +$lang->bug->featureBar['browse']['unconfirmed'] = $lang->bug->unconfirmed; $lang->bug->featureBar['browse']['assigntonull'] = $lang->bug->assignToNull; $lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved; $lang->bug->featureBar['browse']['toclosed'] = $lang->bug->toClosed; diff --git a/module/bug/model.php b/module/bug/model.php index 9e3a8bbd18..d812de7b2d 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -2400,12 +2400,12 @@ class bugModel extends model case 'title': $class = 'confirm' . $bug->confirmed; echo "[{$this->lang->bug->confirmedList[$bug->confirmed]}] "; - if($bug->branch)echo "{$branches[$bug->branch]} "; - if($modulePairs and $bug->module)echo "{$modulePairs[$bug->module]} "; + if($bug->branch and isset($branches[$bug->branch])) echo "{$branches[$bug->branch]} "; + if($bug->module and isset($modulePairs[$bug->module])) echo "{$modulePairs[$bug->module]} "; echo $canView ? html::a($bugLink, $bug->title, null, "style='color: $bug->color'") : "{$bug->title}"; break; case 'branch': - echo $branches[$bug->branch]; + echo zget($branches, $bug->branch, ''); break; case 'project': echo zget($projects, $bug->project, ''); @@ -2467,7 +2467,23 @@ class bugModel extends model echo substr($bug->openedDate, 5, 11); break; case 'openedBuild': - foreach(explode(',', $bug->openedBuild) as $build) echo zget($builds, $build) . ' '; + $builds = array_flip($builds); + foreach(explode(',', $bug->openedBuild) as $build) + { + $buildID = zget($builds, $build, ''); + if($buildID == 'trunk') + { + echo $build; + } + elseif($buildID and common::hasPriv('build', 'view')) + { + echo html::a(helper::createLink('build', 'view', "buildID=$buildID"), $build, '', "title='$bug->openedBuild'"); + } + else + { + echo $build; + } + } break; case 'assignedTo': echo zget($users, $bug->assignedTo, $bug->assignedTo); @@ -2527,9 +2543,8 @@ class bugModel extends model public function sendmail($bugID, $actionID) { $this->loadModel('mail'); - $bug = $this->getByID($bugID); - $productName = $this->loadModel('product')->getById($bug->product)->name; - $users = $this->loadModel('user')->getPairs('noletter'); + $bug = $this->getByID($bugID); + $users = $this->loadModel('user')->getPairs('noletter'); /* Get action info. */ $action = $this->loadModel('action')->getById($actionID); @@ -2564,12 +2579,44 @@ class bugModel extends model ob_end_clean(); chdir($oldcwd); + $sendUsers = $this->getToAndCcList($bug); + if(!$sendUsers) return; + list($toList, $ccList) = $sendUsers; + $subject = $this->getSubject($bug); + + /* Send it. */ + $this->mail->send($toList, $subject, $mailContent, $ccList); + if($this->mail->isError()) trigger_error(join("\n", $this->mail->getError())); + } + + /** + * Get subject. + * + * @param object $bug + * @access public + * @return string + */ + public function getSubject($bug) + { + $productName = $this->loadModel('product')->getById($bug->product)->name; + return 'BUG #'. $bug->id . ' ' . $bug->title . ' - ' . $productName; + } + + /** + * Get toList and ccList. + * + * @param object $bug + * @access public + * @return bool|array + */ + public function getToAndCcList($bug) + { /* Set toList and ccList. */ $toList = $bug->assignedTo; $ccList = trim($bug->mailto, ','); if(empty($toList)) { - if(empty($ccList)) return; + if(empty($ccList)) return false; if(strpos($ccList, ',') === false) { $toList = $ccList; @@ -2587,8 +2634,6 @@ class bugModel extends model $toList = $bug->resolvedBy; } - /* Send it. */ - $this->mail->send($toList, 'BUG #'. $bug->id . ' ' . $bug->title . ' - ' . $productName, $mailContent, $ccList); - if($this->mail->isError()) trigger_error(join("\n", $this->mail->getError())); + return array($toList, $ccList); } } diff --git a/module/bug/view/assignto.html.php b/module/bug/view/assignto.html.php index a4279e4d1e..b06b1b2330 100644 --- a/module/bug/view/assignto.html.php +++ b/module/bug/view/assignto.html.php @@ -20,14 +20,14 @@ js::set('page', 'assignedto');
icons['bug']);?> id;?> createLink('bug', 'view', 'bug=' . $bug->id), $bug->title, '_blank');?> - bug->assignedTo;?> icons['assignTo']);?> + bug->assignBug;?> icons['assignTo']);?>
- + diff --git a/module/bug/view/batchcreate.html.php b/module/bug/view/batchcreate.html.php index 4b6dda944d..8e61ff3e94 100644 --- a/module/bug/view/batchcreate.html.php +++ b/module/bug/view/batchcreate.html.php @@ -39,7 +39,7 @@ foreach(explode(',', $showFields) as $field) - + @@ -77,9 +77,9 @@ foreach(explode(',', $showFields) as $field) $os = $i == 0 ? '' : 'ditto'; $browser = $i == 0 ? '' : 'ditto'; ?> - + - + @@ -90,11 +90,11 @@ foreach(explode(',', $showFields) as $field) - - - - - + + + + + @@ -110,9 +110,9 @@ foreach(explode(',', $showFields) as $field) $os = $i - $nextStart == 0 ? '' : 'ditto'; $browser = $i - $nextStart == 0 ? '' : 'ditto'; ?> - + - + @@ -123,11 +123,11 @@ foreach(explode(',', $showFields) as $field) - - - - - + + + + + @@ -139,9 +139,9 @@ foreach(explode(',', $showFields) as $field)
bug->assignedTo;?>bug->assignBug;?> assignedTo, "class='form-control chosen'");?>
idAB;?> '> product->branch;?>'> bug->module;?> bug->module;?> '>bug->project;?> bug->openedBuild;?> bug->title;?>
'>' style='overflow:visible'> ' style='overflow:visible'> ' style='overflow:visible'> '> '> bug->typeList, $type, "class='form-control'");?>'> bug->priList, $pri, "class='form-control'");?>'>bug->severityList, '', "class='form-control'");?>'> bug->osList, $os, "class='form-control'");?>'> bug->browserList, $browser, "class='form-control'");?>' style='overflow:visible'> bug->typeList, $type, "class='form-control chosen'");?>' style='overflow:visible'> bug->priList, $pri, "class='form-control chosen'");?>' style='overflow:visible'>bug->severityList, '', "class='form-control chosen'");?>' style='overflow:visible'> bug->osList, $os, "class='form-control chosen'");?>' style='overflow:visible'> bug->browserList, $browser, "class='form-control chosen'");?> '>
'>' style='overflow:visible'> ' style='overflow:visible'> ' style='overflow:visible'> '> '> bug->typeList, $type, "class='form-control'");?>'> bug->priList, $pri, "class='form-control'");?>'>bug->severityList, '', "class='form-control'");?>'> bug->osList, $os, "class='form-control'");?>'> bug->browserList, $browser, "class='form-control'");?>' style='overflow:visible'> bug->typeList, $type, "class='form-control chosen'");?>' style='overflow:visible'> bug->priList, $pri, "class='form-control chosen'");?>' style='overflow:visible'>bug->severityList, '', "class='form-control chosen'");?>' style='overflow:visible'> bug->osList, $os, "class='form-control chosen'");?>' style='overflow:visible'> bug->browserList, $browser, "class='form-control chosen'");?> '>
- + - + @@ -152,11 +152,11 @@ foreach(explode(',', $showFields) as $field) - - - - - + + + + + diff --git a/module/bug/view/browse.html.php b/module/bug/view/browse.html.php index d96aed6646..c81ee70997 100644 --- a/module/bug/view/browse.html.php +++ b/module/bug/view/browse.html.php @@ -87,22 +87,22 @@ $currentBrowseType = isset($lang->bug->mySelects[$browseType]) && in_array($brow moduleName, $this->methodName) as $menuItem):?> hidden)) continue;?> config->global->flow == 'onlyTest' and $menuItem->name == 'needconfirm') continue;?> - name, 'QUERY' === 0) ? 'bySearch' : $menuItem->name;?> + name, 'QUERY' === 0) ? 'bySearch' : $menuItem->name;?> name, 'QUERY' === 0) ? (int)substr($menuItem->name, 5) : 0;?> name == 'my'):?> "; - echo html::a('javascript:;', $menuItem->text . " ", '', "data-toggle='dropdown'"); - echo "'; + echo "'; ?> -
  • createLink('bug', 'browse', "productid=$productID&branch=$branch&browseType=$browseType¶m=$param"), $menuItem->text)?>
  • +
  • createLink('bug', 'browse', "productid=$productID&branch=$branch&browseType=$menuBrowseType¶m=$param"), $menuItem->text)?>
  •  bug->byQuery;?>
  • @@ -137,7 +137,7 @@ $currentBrowseType = isset($lang->bug->mySelects[$browseType]) && in_array($brow else { $misc = common::hasPriv('bug', 'create') ? "class='btn btn-primary'" : "class='btn btn-primary disabled'"; - $link = common::hasPriv('bug', 'create') ? $this->createLink('bug', 'create', "productID=$productID&branch=$branch&extra=moduleID=$moduleID") : '#'; + $link = common::hasPriv('bug', 'create') ? $this->createLink('bug', 'create', "productID=$productID&branch=$branch&extra=moduleID=$moduleID") : '#'; echo html::a($link, "" . $lang->bug->create, '', $misc); } @@ -330,7 +330,7 @@ $currentBrowseType = isset($lang->bug->mySelects[$browseType]) && in_array($brow foreach ($memberPairs as $key => $value) { if(empty($key)) continue; - echo "
  • " . html::a("javascript:$(\".table-actions #assignedTo\").val(\"$key\");setFormAction(\"$actionLink\")", $value, '', '') . '
  • '; + echo "
  • " . html::a("javascript:$(\"#assignedTo\").val(\"$key\");setFormAction(\"$actionLink\",\"hiddenwin\")", $value, '', '') . '
  • '; } echo ""; if($withSearch) echo ""; diff --git a/module/bug/view/create.html.php b/module/bug/view/create.html.php index a1ba83fc4f..6936c712b5 100644 --- a/module/bug/view/create.html.php +++ b/module/bug/view/create.html.php @@ -74,15 +74,15 @@ js::set('confirmDeleteTemplate', $lang->bug->confirmDeleteTemplate); unset($lang->bug->typeList['designchange']); unset($lang->bug->typeList['newfeature']); unset($lang->bug->typeList['trackthings']); - echo html::select('type', $lang->bug->typeList, $type, "class='form-control'"); + echo html::select('type', $lang->bug->typeList, $type, "class='form-control chosen'"); ?> bug->os?> - bug->osList, $os, "class='form-control'");?> + bug->osList, $os, "class='form-control chosen'");?> bug->browser?> - bug->browserList, $browser, "class='form-control'");?> + bug->browserList, $browser, "class='form-control chosen'");?> @@ -129,15 +129,15 @@ js::set('confirmDeleteTemplate', $lang->bug->confirmDeleteTemplate); unset($lang->bug->typeList['designchange']); unset($lang->bug->typeList['newfeature']); unset($lang->bug->typeList['trackthings']); - echo html::select('type', $lang->bug->typeList, $type, "class='form-control'"); + echo html::select('type', $lang->bug->typeList, $type, "class='form-control chosen'"); ?> bug->os?> - bug->osList, $os, "class='form-control'");?> + bug->osList, $os, "class='form-control chosen'");?> bug->browser?> - bug->browserList, $browser, "class='form-control'");?> + bug->browserList, $browser, "class='form-control chosen'");?> @@ -165,7 +165,7 @@ js::set('confirmDeleteTemplate', $lang->bug->confirmDeleteTemplate); $hasCustomSeverity = false; foreach($lang->bug->severityList as $severityKey => $severityValue) { - if($severityKey != $severityValue) + if($severityKey != $severityValue or strlen($severityKey) != strlen($severityValue)) { $hasCustomSeverity = true; break; @@ -173,7 +173,7 @@ js::set('confirmDeleteTemplate', $lang->bug->confirmDeleteTemplate); } ?> - bug->severityList, $severity, "class='form-control minw-80px'");?> + bug->severityList, $severity, "class='form-control minw-80px chosen'");?> - + - + - + @@ -151,11 +151,11 @@ js::set('oldResolvedBuild' , $bug->resolvedBuild); - + - + @@ -163,7 +163,10 @@ js::set('oldResolvedBuild' , $bug->resolvedBuild); - +
    %s'>' style='overflow:visible'> ' style='overflow:visible'> ' style='overflow:visible'> '> '> bug->typeList, $type, "class='form-control'");?>'> bug->priList, '', "class='form-control'");?>'>bug->severityList, '', "class='form-control'");?>'> bug->osList, $os, "class='form-control'");?>'> bug->browserList, $browser, "class='form-control'");?>' style='overflow:visible'> bug->typeList, $type, "class='form-control'");?>' style='overflow:visible'> bug->priList, '', "class='form-control'");?>' style='overflow:visible'>bug->severityList, '', "class='form-control'");?>' style='overflow:visible'> bug->osList, $os, "class='form-control'");?>' style='overflow:visible'> bug->browserList, $browser, "class='form-control'");?> '>
    bug->severity;?>bug->severityList, $bug->severity, "class='form-control'");?>bug->severityList, $bug->severity, "class='form-control chosen'");?>
    bug->pri;?>bug->priList, $bug->pri, "class='form-control'");?>bug->priList, $bug->pri, "class='form-control chosen'");?>
    bug->status;?>bug->statusList, $bug->status, "class='form-control'");?>bug->statusList, $bug->status, "class='form-control chosen'");?>
    bug->confirmed;?>
    bug->os;?>bug->osList, $bug->os, "class='form-control'");?>bug->osList, $bug->os, "class='form-control chosen'");?>
    bug->browser;?>bug->browserList, $bug->browser, "class='form-control'");?>bug->browserList, $bug->browser, "class='form-control chosen'");?>
    bug->keywords;?>
    bug->mailto;?>mailto), 'class="form-control chosen" multiple');?> + mailto), 'class="form-control chosen" multiple');?> + fetch('my', 'buildContactLists');?> +
    diff --git a/module/bug/view/report.html.php b/module/bug/view/report.html.php index 2b3242d339..99d13ee63a 100644 --- a/module/bug/view/report.html.php +++ b/module/bug/view/report.html.php @@ -40,8 +40,13 @@
    - bug->report->common;?> - report->notice->help?> + bug->report->common;?> +
    + report->typeList as $type => $typeName):?> + + +
    + report->notice->help?>
    @@ -81,4 +86,8 @@ + + + + diff --git a/module/bug/view/resolve.html.php b/module/bug/view/resolve.html.php index 8b4bde42fc..f2efd953d5 100644 --- a/module/bug/view/resolve.html.php +++ b/module/bug/view/resolve.html.php @@ -28,7 +28,7 @@ js::set('productID' , $bug->product);
    - + diff --git a/module/bug/view/sendmail.html.php b/module/bug/view/sendmail.html.php index bd70d8ee20..f949c6399e 100644 --- a/module/bug/view/sendmail.html.php +++ b/module/bug/view/sendmail.html.php @@ -16,7 +16,10 @@ diff --git a/module/bug/view/view.html.php b/module/bug/view/view.html.php index 1f26194dbf..1cfa6ae009 100644 --- a/module/bug/view/view.html.php +++ b/module/bug/view/view.html.php @@ -107,7 +107,7 @@
    bug->resolution;?>bug->resolution;?> bug->resolutionList, '', 'class=form-control onchange=setDuplicate(this.value)');?>
    - +
    config->mail, 'domain', common::getSysURL()) . helper::createLink('bug', 'view', "bugID=$bug->id"), $mailTitle, '', "style='color: #333; text-decoration: underline;'");?> + color) ? '#333' : $bug->color;?> + config->mail, 'domain', common::getSysURL()) . helper::createLink('bug', 'view', "bugID=$bug->id"), $mailTitle, '', "style='color: {$color}; text-decoration: underline;'");?> +
    - + session->currentProductType != 'normal'):?> @@ -239,7 +239,7 @@
    bug->product;?>bug->product;?> product", $productName)) echo $productName;?>
    - + @@ -288,7 +288,7 @@
    bug->openedBy;?>bug->openedBy;?> openedBy) . $lang->at . $bug->openedDate;?>
    - + - + - + diff --git a/module/build/view/view.html.php b/module/build/view/view.html.php index 2a5406e30f..e4ad7a3649 100644 --- a/module/build/view/view.html.php +++ b/module/build/view/view.html.php @@ -102,7 +102,7 @@ tfoot tr td .table-actions .btn{display:none;} - + @@ -162,7 +162,7 @@ tfoot tr td .table-actions .btn{display:none;} - + diff --git a/module/common/lang/en.php b/module/common/lang/en.php index 2946a1b829..7329269936 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -27,9 +27,10 @@ $lang->aboutZenTao = 'ZenTao'; $lang->profile = 'Profile'; $lang->changePassword = 'Password'; $lang->runInfo = "
    Time %s MS, Memory %s KB, Query %s.
    "; -$lang->agreement = "I have read and agreed to the terms and conditions of Z PUBLIC LICENSE 1.2 . Without authorization, I should not remove, hide, or cover any logos/links of ZenTao."; +$lang->agreement = "I have read and agreed to the terms and conditions of Z PUBLIC LICENSE 1.2 . Without authorization, I should not remove, hide or cover any logos/links of ZenTao."; $lang->reset = 'Reset'; +$lang->cancel = 'Cancel'; $lang->refresh = 'Refresh'; $lang->edit = 'Edit'; $lang->delete = 'Delete'; @@ -46,7 +47,7 @@ $lang->goback = 'Back'; $lang->goPC = 'PC'; $lang->more = 'More'; $lang->day = 'Day'; -$lang->customConfig = 'Custom'; +$lang->customConfig = 'Custom Configuration'; $lang->public = 'Public'; $lang->trunk = 'Trunk'; $lang->sort = 'Order'; @@ -93,7 +94,7 @@ $lang->workingHour = 'Hour'; $lang->idAB = 'ID'; $lang->priAB = 'P'; $lang->statusAB = 'Status'; -$lang->openedByAB = 'Created by'; +$lang->openedByAB = 'Creator'; $lang->assignedToAB = 'Assignee'; $lang->typeAB = 'Type'; @@ -102,14 +103,17 @@ $lang->common->common = 'Common Module'; /* 主导航菜单。*/ $lang->menu = new stdclass(); -$lang->menu->my = 'Dashboard|my|index'; -$lang->menu->product = $lang->productCommon . '|product|index'; -$lang->menu->project = $lang->projectCommon . '|project|index'; -$lang->menu->qa = 'QA|qa|index'; -$lang->menu->doc = 'Doc|doc|index'; -$lang->menu->report = 'Report|report|index'; -$lang->menu->company = 'Company|company|index'; -$lang->menu->admin = 'Admin|admin|index'; +$lang->menu->my = 'Dashboard|my|index'; +$lang->menu->product = $lang->productCommon . '|product|index'; +$lang->menu->project = $lang->projectCommon . '|project|index'; +$lang->menu->qa = 'QA|qa|index'; +$lang->menu->doc = 'Doc|doc|index'; +$lang->menu->report = 'Report|report|index'; +$lang->menu->company = 'Company|company|index'; + +$lang->adminMenu = 'Admin|admin|index'; + +$lang->dividerMenu = ',qa,'; /* 查询条中可以选择的对象列表。*/ $lang->searchObjects['bug'] = 'Bug'; @@ -163,9 +167,8 @@ $lang->index->menu->project = "{$lang->projectCommon}|project|browse"; $lang->my = new stdclass(); $lang->my->menu = new stdclass(); -$lang->my->menu->account = array('link' => ' %s' . $lang->arrow . '', 'fixed' => true); $lang->my->menu->index = 'Home|my|index'; -$lang->my->menu->todo = array('link' => 'To-Do|my|todo|', 'subModule' => 'todo'); +$lang->my->menu->calendar = array('link' => 'Calendar|my|calendar|', 'subModule' => 'todo', 'alias' => 'todo'); $lang->my->menu->task = array('link' => 'Task|my|task|', 'subModule' => 'task'); $lang->my->menu->bug = array('link' => 'Bug|my|bug|', 'subModule' => 'bug'); $lang->my->menu->testtask = array('link' => 'Test Task|my|testtask|', 'subModule' => 'testcase,testtask', 'alias' => 'testcase'); @@ -337,16 +340,15 @@ $lang->user->menu = $lang->company->menu; $lang->admin = new stdclass(); $lang->admin->menu = new stdclass(); $lang->admin->menu->index = array('link' => 'Home|admin|index', 'alias' => 'register,certifytemail,certifyztmobile,ztcompany'); + $lang->admin->menu->custom = array('link' => 'Custom|custom|set', 'subModule' => 'custom'); -$lang->admin->menu->mail = array('link' => 'Email|mail|index', 'subModule' => 'mail'); +$lang->admin->menu->message = array('link' => 'Message|message|index', 'subModule' => 'message,mail,webhook'); $lang->admin->menu->backup = array('link' => 'Backup|backup|index', 'subModule' => 'backup'); $lang->admin->menu->safe = array('link' => 'Security|admin|safe', 'alias' => 'checkweak'); $lang->admin->menu->cron = array('link' => 'Cron|cron|index', 'subModule' => 'cron'); $lang->admin->menu->trashes = array('link' => 'Recycle|action|trash', 'subModule' => 'action'); $lang->admin->menu->dev = array('link' => 'Develop|dev|api', 'alias' => 'db', 'subModule' => 'dev,editor'); -$lang->admin->menu->api = array('link' => 'API|webhook|browse', 'alias' => 'create,edit', 'subModule' => 'entry,webhook'); $lang->admin->menu->sso = 'RangerTeam|admin|sso'; -//$lang->admin->menu->extension = array('link' => 'Extension|extension|browse', 'subModule' => 'extension'); $lang->convert = new stdclass(); $lang->upgrade = new stdclass(); @@ -360,6 +362,7 @@ $lang->cron = new stdclass(); $lang->dev = new stdclass(); $lang->entry = new stdclass(); $lang->webhook = new stdclass(); +$lang->message = new stdclass(); $lang->search = new stdclass(); $lang->convert->menu = $lang->admin->menu; @@ -374,6 +377,7 @@ $lang->mail->menu = $lang->admin->menu; $lang->dev->menu = $lang->admin->menu; $lang->entry->menu = $lang->admin->menu; $lang->webhook->menu = $lang->admin->menu; +$lang->message->menu = $lang->admin->menu; /* 菜单分组。*/ $lang->menugroup = new stdclass(); @@ -407,6 +411,7 @@ $lang->menugroup->mail = 'admin'; $lang->menugroup->dev = 'admin'; $lang->menugroup->entry = 'admin'; $lang->menugroup->webhook = 'admin'; +$lang->menugroup->message = 'admin'; /* 错误提示信息。*/ $lang->error = new stdclass(); @@ -423,6 +428,7 @@ $lang->error->int = array("『%s』should be numbers", "『%s』shou $lang->error->float = "『%s』should be numbers, decimals included."; $lang->error->email = "『%s』should be valid Email."; $lang->error->date = "『%s』should be valid date."; +$lang->error->datetime = "『%s』should be valid date."; $lang->error->code = "『%s』should be letters or numbers."; $lang->error->account = "『%s』should be valid account."; $lang->error->passwordsame = "Two passwords should be consistent."; @@ -433,28 +439,9 @@ $lang->error->noData = 'No Data'; $lang->error->editedByOther = 'This record might have been changed. Please refresh and try to edit again!'; $lang->error->tutorialData = 'No data can be imported in tutorial mode. Please exit tutorial first!'; -if(!defined('PARAM_CODE_MISSING')) define('PARAM_CODE_MISSING', 301); -if(!defined('PARAM_TOKEN_MISSING')) define('PARAM_TOKEN_MISSING', 302); -if(!defined('INVALID_ENTRY')) define('INVALID_ENTRY', 311); -if(!defined('EMPTY_KEY')) define('EMPTY_KEY', 312); -if(!defined('IP_DENIED')) define('IP_DENIED', 321); -if(!defined('INVALID_TOKEN')) define('INVALID_TOKEN', 331); -if(!defined('SESSION_CODE_MISSING')) define('SESSION_CODE_MISSING', 341); -if(!defined('SESSION_VERIFY_FAILED')) define('SESSION_VERIFY_FAILED', 342); - -$lang->error->entry = array(); -$lang->error->entry['PARAM_CODE_MISSING'] = 'Param code is missing.'; -$lang->error->entry['PARAM_TOKEN_MISSING'] = 'Param token is missing.'; -$lang->error->entry['INVALID_ENTRY'] = 'Entry does not exist.'; -$lang->error->entry['EMPTY_KEY'] = 'Key of entry is missing.'; -$lang->error->entry['IP_DENIED'] = 'IP is denied.'; -$lang->error->entry['INVALID_TOKEN'] = 'Invalid token.'; -$lang->error->entry['SESSION_CODE_MISSING'] = 'Session code is missing.'; -$lang->error->entry['SESSION_VERIFY_FAILED'] = 'Session verification failed.'; - /* 分页信息。*/ $lang->pager = new stdclass(); -$lang->pager->noRecord = "No History"; +$lang->pager->noRecord = "No Records"; $lang->pager->digest = " %s in total. %s %s/%s   "; $lang->pager->recPerPage = " %s per page"; $lang->pager->first = ""; @@ -468,17 +455,18 @@ $lang->pager->summery = "%s-%s of %s."; $lang->proVersion = "ZenTao Pro   "; $lang->downNotify = "Download Desktop Notification"; +$lang->website = "http://www.zentao.pm"; $lang->suhosinInfo = "Warning! Data is reaching the limit. Please change sohusin.post.max_vars and sohusin.request.max_vars (set larger %s value) in php.ini, then save and restart Apache or php-fpm, or some data will not be saved."; $lang->maxVarsInfo = "Warning! Data is reaching the limit. Please change max_input_vars (set larger %s value) in php.ini, then save and restart Apache or php-fpm, or some data will not be saved."; -$lang->pasteTextInfo = "Paste text here. Each line will be a header of each data record. "; +$lang->pasteTextInfo = "Paste text here. Each line will be the title of each record. "; $lang->noticeImport = "

    Imported data contains data that has already existed in system. Please confirm you actions on the date

    Override New Insertion

    "; $lang->noResultsMatch = "No results match!"; $lang->searchMore = "More results:"; $lang->chooseUsersToMail = "Choose users that will be notified."; $lang->browserNotice = 'Your current browser might not show the best effect. Please use Chrome, Firefox, IE9+, Opera or Safari.'; -$lang->noticePasteImg = "Paste image here."; +$lang->noticePasteImg = "Support pasting images."; /* 时间格式设置。*/ if(!defined('DT_DATETIME1')) define('DT_DATETIME1', 'Y-m-d H:i:s'); @@ -551,8 +539,8 @@ $lang->icons['post'] = 'edit'; $lang->icons['batchCreate'] = 'plus-sign'; $lang->icons['batchEdit'] = 'edit-sign'; $lang->icons['batchClose'] = 'off'; -$lang->icons['edit'] = 'pencil'; -$lang->icons['delete'] = 'remove'; +$lang->icons['edit'] = 'edit'; +$lang->icons['delete'] = 'trash'; $lang->icons['copy'] = 'copy'; $lang->icons['report'] = 'bar-chart'; $lang->icons['export'] = 'download-alt'; diff --git a/module/common/lang/menuOrder.php b/module/common/lang/menuOrder.php index 482565d152..e6edf25c96 100644 --- a/module/common/lang/menuOrder.php +++ b/module/common/lang/menuOrder.php @@ -16,7 +16,7 @@ $lang->index->menuOrder[10] = 'project'; /* my menu order. */ $lang->my->menuOrder[5] = 'account'; $lang->my->menuOrder[10] = 'index'; -$lang->my->menuOrder[15] = 'todo'; +$lang->my->menuOrder[15] = 'calendar'; $lang->my->menuOrder[20] = 'task'; $lang->my->menuOrder[25] = 'bug'; $lang->my->menuOrder[30] = 'testtask'; @@ -112,6 +112,7 @@ $lang->user->menuOrder = $lang->company->menuOrder; $lang->admin->menuOrder[5] = 'index'; $lang->admin->menuOrder[10] = 'extension'; $lang->admin->menuOrder[15] = 'custom'; +$lang->admin->menuOrder[19] = 'message'; $lang->admin->menuOrder[20] = 'mail'; $lang->admin->menuOrder[25] = 'custom'; $lang->admin->menuOrder[30] = 'convert'; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 7a19df6df4..86461e1c18 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -23,13 +23,14 @@ $lang->welcome = "%s项目管理系统"; $lang->logout = '退出'; $lang->login = '登录'; $lang->help = '帮助'; -$lang->aboutZenTao = '关于'; +$lang->aboutZenTao = '关于禅道'; $lang->profile = '个人档案'; $lang->changePassword = '更改密码'; $lang->runInfo = "
    时间: %s 毫秒, 内存: %s KB, 查询: %s.
    "; $lang->agreement = "已阅读并同意《Z PUBLIC LICENSE授权协议1.2》。未经许可,不得去除、隐藏或遮掩禅道软件的任何标志及链接。"; $lang->reset = '重填'; +$lang->cancel = '取消'; $lang->refresh = '刷新'; $lang->edit = '编辑'; $lang->delete = '删除'; @@ -86,9 +87,9 @@ $lang->loading = '稍候...'; $lang->notFound = '抱歉,您访问的对象并不存在!'; $lang->showAll = '[[全部显示]]'; -$lang->future = '未来'; -$lang->year = '年'; -$lang->workingHour = '工时'; +$lang->future = '未来'; +$lang->year = '年'; +$lang->workingHour = '工时'; $lang->idAB = 'ID'; $lang->priAB = 'P'; @@ -102,14 +103,17 @@ $lang->common->common = '公有模块'; /* 主导航菜单。*/ $lang->menu = new stdclass(); -$lang->menu->my = ' 我的地盘|my|index'; -$lang->menu->product = $lang->productCommon . '|product|index'; -$lang->menu->project = $lang->projectCommon . '|project|index'; -$lang->menu->qa = '测试|qa|index'; -$lang->menu->doc = '文档|doc|index'; -$lang->menu->report = '统计|report|index'; -$lang->menu->company = '组织|company|index'; -$lang->menu->admin = '后台|admin|index'; +$lang->menu->my = ' 我的地盘|my|index'; +$lang->menu->product = $lang->productCommon . '|product|index'; +$lang->menu->project = $lang->projectCommon . '|project|index'; +$lang->menu->qa = '测试|qa|index'; +$lang->menu->doc = '文档|doc|index'; +$lang->menu->report = '统计|report|index'; +$lang->menu->company = '组织|company|index'; + +$lang->adminMenu = '后台|admin|index'; + +$lang->dividerMenu = ',qa,'; /* 查询条中可以选择的对象列表。*/ $lang->searchObjects['bug'] = 'Bug'; @@ -145,12 +149,12 @@ $lang->exportTypeList['selected'] = '选中记录'; $lang->lang = 'Language'; /* 风格列表。*/ -$lang->theme = '主题'; -$lang->themes['default'] = '默认'; -$lang->themes['green'] = '绿色'; -$lang->themes['red'] = '红色'; -$lang->themes['lightblue'] = '亮蓝'; -$lang->themes['blackberry'] = '黑莓'; +$lang->theme = '主题'; +$lang->themes['default'] = '默认'; +$lang->themes['green'] = '绿色'; +$lang->themes['red'] = '红色'; +$lang->themes['lightblue'] = '亮蓝'; +$lang->themes['blackberry'] = '黑莓'; /* 首页菜单设置。*/ $lang->index = new stdclass(); @@ -163,9 +167,8 @@ $lang->index->menu->project = "浏览{$lang->projectCommon}|project|browse"; $lang->my = new stdclass(); $lang->my->menu = new stdclass(); -$lang->my->menu->account = array('link' => ' %s' . $lang->arrow . '', 'fixed' => true); $lang->my->menu->index = '首页|my|index'; -$lang->my->menu->todo = array('link' => '待办|my|todo|', 'subModule' => 'todo'); +$lang->my->menu->calendar = array('link' => '日程|my|calendar|', 'subModule' => 'todo', 'alias' => 'todo'); $lang->my->menu->task = array('link' => '任务|my|task|', 'subModule' => 'task'); $lang->my->menu->bug = array('link' => 'Bug|my|bug|', 'subModule' => 'bug'); $lang->my->menu->testtask = array('link' => '测试|my|testtask|', 'subModule' => 'testcase,testtask', 'alias' => 'testcase'); @@ -187,20 +190,20 @@ $lang->score->menu = $lang->my->menu; $lang->product = new stdclass(); $lang->product->menu = new stdclass(); -$lang->product->menu->list = array('link' => '%s', 'fixed' => true); -$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story'); -$lang->product->menu->dynamic = '动态|product|dynamic|productID=%s'; -$lang->product->menu->plan = array('link' => '计划|productplan|browse|productID=%s', 'subModule' => 'productplan'); -$lang->product->menu->release = array('link' => '发布|release|browse|productID=%s', 'subModule' => 'release'); -$lang->product->menu->roadmap = '路线图|product|roadmap|productID=%s'; -$lang->product->menu->doc = array('link' => '文档|doc|objectLibs|type=product&objectID=%s&from=product', 'subModule' => 'doc'); -$lang->product->menu->branch = '@branch@|branch|manage|productID=%s'; -$lang->product->menu->module = '模块|tree|browse|productID=%s&view=story'; -$lang->product->menu->view = array('link' => '概况|product|view|productID=%s', 'alias' => 'edit'); -$lang->product->menu->project = "{$lang->projectCommon}|product|project|status=all&productID=%s"; -$lang->product->menu->create = array('link' => " 添加{$lang->productCommon}|product|create", 'float' => 'right'); -$lang->product->menu->all = array('link' => " 所有{$lang->productCommon}|product|all|productID=%s", 'float' => 'right'); -$lang->product->menu->index = array('link' => "{$lang->productCommon}主页|product|index|locate=no", 'float' => 'right'); +$lang->product->menu->list = array('link' => '%s', 'fixed' => true); +$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story'); +$lang->product->menu->dynamic = '动态|product|dynamic|productID=%s'; +$lang->product->menu->plan = array('link' => '计划|productplan|browse|productID=%s', 'subModule' => 'productplan'); +$lang->product->menu->release = array('link' => '发布|release|browse|productID=%s', 'subModule' => 'release'); +$lang->product->menu->roadmap = '路线图|product|roadmap|productID=%s'; +$lang->product->menu->doc = array('link' => '文档|doc|objectLibs|type=product&objectID=%s&from=product', 'subModule' => 'doc'); +$lang->product->menu->branch = '@branch@|branch|manage|productID=%s'; +$lang->product->menu->module = '模块|tree|browse|productID=%s&view=story'; +$lang->product->menu->view = array('link' => '概况|product|view|productID=%s', 'alias' => 'edit'); +$lang->product->menu->project = "{$lang->projectCommon}|product|project|status=all&productID=%s"; +$lang->product->menu->create = array('link' => " 添加{$lang->productCommon}|product|create", 'float' => 'right'); +$lang->product->menu->all = array('link' => " 所有{$lang->productCommon}|product|all|productID=%s", 'float' => 'right'); +$lang->product->menu->index = array('link' => "{$lang->productCommon}主页|product|index|locate=no", 'float' => 'right'); $lang->story = new stdclass(); $lang->productplan = new stdclass(); @@ -216,20 +219,20 @@ $lang->release->menu = $lang->product->menu; $lang->project = new stdclass(); $lang->project->menu = new stdclass(); -$lang->project->menu->list = array('link' => '%s', 'fixed' => true); -$lang->project->menu->task = array('link' => '任务|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'grouptask,importtask,burn,importbug,kanban,printkanban,tree'); -$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory,storykanban'); -$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; -$lang->project->menu->dynamic = '动态|project|dynamic|projectID=%s'; -$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build'); -$lang->project->menu->testtask = array('link' => '测试单|project|testtask|projectID=%s'); -$lang->project->menu->team = array('link' => '团队|project|team|projectID=%s', 'alias' => 'managemembers'); -$lang->project->menu->doc = array('link' => '文档|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc'); -$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s'; -$lang->project->menu->view = array('link' => '概况|project|view|projectID=%s', 'alias' => 'edit,start,suspend,putoff,close'); -$lang->project->menu->create = array('link' => " 添加{$lang->projectCommon}|project|create", 'float' => 'right'); -$lang->project->menu->all = array('link' => " 所有{$lang->projectCommon}|project|all|status=undone&projectID=%s", 'float' => 'right'); -$lang->project->menu->index = array('link' => "{$lang->projectCommon}主页|project|index|locate=no", 'float' => 'right'); +$lang->project->menu->list = array('link' => '%s', 'fixed' => true); +$lang->project->menu->task = array('link' => '任务|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'grouptask,importtask,burn,importbug,kanban,printkanban,tree'); +$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory,storykanban'); +$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; +$lang->project->menu->dynamic = '动态|project|dynamic|projectID=%s'; +$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build'); +$lang->project->menu->testtask = array('link' => '测试单|project|testtask|projectID=%s'); +$lang->project->menu->team = array('link' => '团队|project|team|projectID=%s', 'alias' => 'managemembers'); +$lang->project->menu->doc = array('link' => '文档|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc'); +$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s'; +$lang->project->menu->view = array('link' => '概况|project|view|projectID=%s', 'alias' => 'edit,start,suspend,putoff,close'); +$lang->project->menu->create = array('link' => " 添加{$lang->projectCommon}|project|create", 'float' => 'right'); +$lang->project->menu->all = array('link' => " 所有{$lang->projectCommon}|project|all|status=undone&projectID=%s", 'float' => 'right'); +$lang->project->menu->index = array('link' => "{$lang->projectCommon}主页|project|index|locate=no", 'float' => 'right'); $lang->task = new stdclass(); $lang->build = new stdclass(); @@ -296,9 +299,9 @@ $lang->caselib->menu->index = array('link' => "测 $lang->doc = new stdclass(); $lang->doc->menu = new stdclass(); -$lang->doc->menu->list = array('link' => '%s', 'fixed' => true); -$lang->doc->menu->crumb = array('link' => '%s', 'fixed' => true); -$lang->doc->menu->create = array('link' => ' 添加文档库|doc|createLib', 'float' => 'right'); +$lang->doc->menu->list = array('link' => '%s', 'fixed' => true); +$lang->doc->menu->crumb = array('link' => '%s', 'fixed' => true); +$lang->doc->menu->create = array('link' => ' 添加文档库|doc|createLib', 'float' => 'right'); /* 统计视图菜单设置。*/ $lang->report = new stdclass(); @@ -339,13 +342,12 @@ $lang->admin->menu = new stdclass(); $lang->admin->menu->index = array('link' => '首页|admin|index', 'alias' => 'register,certifytemail,certifyztmobile,ztcompany'); $lang->admin->menu->extension = array('link' => '插件|extension|browse', 'subModule' => 'extension'); $lang->admin->menu->custom = array('link' => '自定义|custom|set', 'subModule' => 'custom'); -$lang->admin->menu->mail = array('link' => '发信|mail|index', 'subModule' => 'mail'); +$lang->admin->menu->message = array('link' => '消息|message|index', 'subModule' => 'message,mail,webhook'); $lang->admin->menu->backup = array('link' => '备份|backup|index', 'subModule' => 'backup'); $lang->admin->menu->safe = array('link' => '安全|admin|safe', 'alias' => 'checkweak'); $lang->admin->menu->cron = array('link' => '计划任务|cron|index', 'subModule' => 'cron'); $lang->admin->menu->trashes = array('link' => '回收站|action|trash', 'subModule' => 'action'); $lang->admin->menu->dev = array('link' => '二次开发|dev|api', 'alias' => 'db', 'subModule' => 'dev,editor'); -$lang->admin->menu->api = array('link' => '接口|webhook|browse', 'alias' => 'create,edit', 'subModule' => 'entry,webhook'); $lang->admin->menu->sso = '然之集成|admin|sso'; $lang->convert = new stdclass(); @@ -360,6 +362,7 @@ $lang->cron = new stdclass(); $lang->dev = new stdclass(); $lang->entry = new stdclass(); $lang->webhook = new stdclass(); +$lang->message = new stdclass(); $lang->search = new stdclass(); $lang->convert->menu = $lang->admin->menu; @@ -374,6 +377,7 @@ $lang->mail->menu = $lang->admin->menu; $lang->dev->menu = $lang->admin->menu; $lang->entry->menu = $lang->admin->menu; $lang->webhook->menu = $lang->admin->menu; +$lang->message->menu = $lang->admin->menu; /* 菜单分组。*/ $lang->menugroup = new stdclass(); @@ -407,6 +411,7 @@ $lang->menugroup->mail = 'admin'; $lang->menugroup->dev = 'admin'; $lang->menugroup->entry = 'admin'; $lang->menugroup->webhook = 'admin'; +$lang->menugroup->message = 'admin'; /* 错误提示信息。*/ $lang->error = new stdclass(); @@ -423,6 +428,7 @@ $lang->error->int = array("『%s』应当是数字。", "『%s』应 $lang->error->float = "『%s』应当是数字,可以是小数。"; $lang->error->email = "『%s』应当为合法的EMAIL。"; $lang->error->date = "『%s』应当为合法的日期。"; +$lang->error->datetime = "『%s』应当为合法的日期。"; $lang->error->code = "『%s』应当为字母或数字的组合。"; $lang->error->account = "『%s』应当为合法的用户名。"; $lang->error->passwordsame = "两次密码应当相等。"; @@ -433,25 +439,6 @@ $lang->error->noData = '没有数据'; $lang->error->editedByOther = '该记录可能已经被改动。请刷新页面重新编辑!'; $lang->error->tutorialData = '新手模式下不会插入数据,请退出新手模式操作'; -if(!defined('PARAM_CODE_MISSING')) define('PARAM_CODE_MISSING', 301); -if(!defined('PARAM_TOKEN_MISSING')) define('PARAM_TOKEN_MISSING', 302); -if(!defined('INVALID_ENTRY')) define('INVALID_ENTRY', 311); -if(!defined('EMPTY_KEY')) define('EMPTY_KEY', 312); -if(!defined('IP_DENIED')) define('IP_DENIED', 321); -if(!defined('INVALID_TOKEN')) define('INVALID_TOKEN', 331); -if(!defined('SESSION_CODE_MISSING')) define('SESSION_CODE_MISSING', 341); -if(!defined('SESSION_VERIFY_FAILED')) define('SESSION_VERIFY_FAILED', 342); - -$lang->error->entry = array(); -$lang->error->entry['PARAM_CODE_MISSING'] = '缺少code参数'; -$lang->error->entry['PARAM_TOKEN_MISSING'] = '缺少token参数'; -$lang->error->entry['INVALID_ENTRY'] = '应用不存在'; -$lang->error->entry['EMPTY_KEY'] = '应用未设置密钥'; -$lang->error->entry['IP_DENIED'] = '该IP访问被限制访问'; -$lang->error->entry['INVALID_TOKEN'] = '不合法的token参数'; -$lang->error->entry['SESSION_CODE_MISSING'] = '缺少session code'; -$lang->error->entry['SESSION_VERIFY_FAILED'] = 'session验证失败'; - /* 分页信息。*/ $lang->pager = new stdclass(); $lang->pager->noRecord = "暂时没有记录"; @@ -466,31 +453,32 @@ $lang->pager->previousPage = "上一页"; $lang->pager->nextPage = "下一页"; $lang->pager->summery = "第 %s-%s 项,共 %s 项"; -$lang->proVersion = "专业版   "; -$lang->downNotify = "下载桌面提醒"; +$lang->proVersion = "专业版   "; +$lang->downNotify = "下载桌面提醒"; +$lang->website = "http://www.zentao.net"; $lang->suhosinInfo = "警告:数据太多,请在php.ini中修改sohusin.post.max_vars和sohusin.request.max_vars(大于%s的数)。 保存并重新启动apache或php-fpm,否则会造成部分数据无法保存。"; $lang->maxVarsInfo = "警告:数据太多,请在php.ini中修改max_input_vars(大于%s的数)。 保存并重新启动apache或php-fpm,否则会造成部分数据无法保存。"; $lang->pasteTextInfo = "粘贴文本到文本域中,每行文字作为一条数据的标题。"; $lang->noticeImport = "

    导入数据中,含有已经存在系统的数据,请确认这些数据要覆盖或者全新插入

    覆盖 全新插入

    "; -$lang->noResultsMatch = "没有匹配结果"; -$lang->searchMore = "搜索此关键字的更多结果:"; -$lang->chooseUsersToMail = "选择要发信通知的用户..."; -$lang->browserNotice = '你目前使用的浏览器可能无法得到最佳浏览效果,建议使用Chrome、火狐、IE9+、Opera、Safari浏览器。'; -$lang->noticePasteImg = "可以在编辑器直接贴图。"; +$lang->noResultsMatch = "没有匹配结果"; +$lang->searchMore = "搜索此关键字的更多结果:"; +$lang->chooseUsersToMail = "选择要发信通知的用户..."; +$lang->browserNotice = '你目前使用的浏览器可能无法得到最佳浏览效果,建议使用Chrome、火狐、IE9+、Opera、Safari浏览器。'; +$lang->noticePasteImg = "可以在编辑器直接贴图。"; /* 时间格式设置。*/ -if(!defined('DT_DATETIME1')) define('DT_DATETIME1', 'Y-m-d H:i:s'); -if(!defined('DT_DATETIME2')) define('DT_DATETIME2', 'y-m-d H:i'); -if(!defined('DT_MONTHTIME1'))define('DT_MONTHTIME1', 'n/d H:i'); -if(!defined('DT_MONTHTIME2'))define('DT_MONTHTIME2', 'n月d日 H:i'); -if(!defined('DT_DATE1')) define('DT_DATE1', 'Y-m-d'); -if(!defined('DT_DATE2')) define('DT_DATE2', 'Ymd'); -if(!defined('DT_DATE3')) define('DT_DATE3', 'Y年m月d日'); -if(!defined('DT_DATE4')) define('DT_DATE4', 'n月j日'); -if(!defined('DT_TIME1')) define('DT_TIME1', 'H:i:s'); -if(!defined('DT_TIME2')) define('DT_TIME2', 'H:i'); +if(!defined('DT_DATETIME1')) define('DT_DATETIME1', 'Y-m-d H:i:s'); +if(!defined('DT_DATETIME2')) define('DT_DATETIME2', 'y-m-d H:i'); +if(!defined('DT_MONTHTIME1')) define('DT_MONTHTIME1', 'n/d H:i'); +if(!defined('DT_MONTHTIME2')) define('DT_MONTHTIME2', 'n月d日 H:i'); +if(!defined('DT_DATE1')) define('DT_DATE1', 'Y-m-d'); +if(!defined('DT_DATE2')) define('DT_DATE2', 'Ymd'); +if(!defined('DT_DATE3')) define('DT_DATE3', 'Y年m月d日'); +if(!defined('DT_DATE4')) define('DT_DATE4', 'n月j日'); +if(!defined('DT_TIME1')) define('DT_TIME1', 'H:i:s'); +if(!defined('DT_TIME2')) define('DT_TIME2', 'H:i'); /* datepicker 时间*/ $lang->datepicker = new stdclass(); @@ -551,8 +539,8 @@ $lang->icons['post'] = 'edit'; $lang->icons['batchCreate'] = 'plus-sign'; $lang->icons['batchEdit'] = 'edit-sign'; $lang->icons['batchClose'] = 'off'; -$lang->icons['edit'] = 'pencil'; -$lang->icons['delete'] = 'remove'; +$lang->icons['edit'] = 'edit'; +$lang->icons['delete'] = 'trash'; $lang->icons['copy'] = 'copy'; $lang->icons['report'] = 'bar-chart'; $lang->icons['export'] = 'download-alt'; @@ -608,7 +596,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyStory') /* Adjust sub menu of product module. */ unset($lang->product->menu->project); unset($lang->product->menu->doc); - + /* Rename product module. */ $lang->menu->product = "{$lang->productCommon}|product|index"; @@ -761,15 +749,15 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest') $lang->testtask->menu->report = array('link' => '报告|testreport|browse', 'alias' => 'view,create,edit'); $lang->testtask->menu->create = array('link' => " 提交测试|testtask|create|productID=%s", 'float' => 'right'); - $lang->testtask->menuOrder[5] = 'product'; - $lang->testtask->menuOrder[10] = 'scope'; - $lang->testtask->menuOrder[15] = 'wait'; - $lang->testtask->menuOrder[20] = 'doing'; - $lang->testtask->menuOrder[25] = 'blocked'; - $lang->testtask->menuOrder[30] = 'done'; - $lang->testtask->menuOrder[35] = 'totalStatus'; - $lang->testtask->menuOrder[40] = 'report'; - $lang->testtask->menuOrder[45] = 'create'; + $lang->testtask->menuOrder[5] = 'product'; + $lang->testtask->menuOrder[10] = 'scope'; + $lang->testtask->menuOrder[15] = 'wait'; + $lang->testtask->menuOrder[20] = 'doing'; + $lang->testtask->menuOrder[25] = 'blocked'; + $lang->testtask->menuOrder[30] = 'done'; + $lang->testtask->menuOrder[35] = 'totalStatus'; + $lang->testtask->menuOrder[40] = 'report'; + $lang->testtask->menuOrder[45] = 'create'; $lang->testreport->menu = $lang->testtask->menu; $lang->testreport->menuOrder = $lang->testtask->menuOrder; @@ -806,7 +794,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest') $lang->build->menu = $lang->product->menu; $lang->build->menuOrder = $lang->product->menuOrder; - + /* Adjust menu group. */ $lang->menugroup->bug = 'bug'; $lang->menugroup->testcase = 'testcase'; @@ -814,8 +802,8 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest') $lang->menugroup->testsuite = 'testsuite'; $lang->menugroup->testreport = 'testtask'; $lang->menugroup->build = 'product'; - - /* Adjust search objects. */ + + /* Adjust search objects. */ unset($lang->searchObjects['story']); unset($lang->searchObjects['task']); unset($lang->searchObjects['release']); diff --git a/module/common/lang/zh-tw.php b/module/common/lang/zh-tw.php index 3c1df43da5..8b36dffa47 100644 --- a/module/common/lang/zh-tw.php +++ b/module/common/lang/zh-tw.php @@ -23,7 +23,7 @@ $lang->welcome = "%s項目管理系統"; $lang->logout = '退出'; $lang->login = '登錄'; $lang->help = '幫助'; -$lang->aboutZenTao = '關於'; +$lang->aboutZenTao = '關於禪道'; $lang->profile = '個人檔案'; $lang->changePassword = '更改密碼'; $lang->runInfo = "
    時間: %s 毫秒, 內存: %s KB, 查詢: %s.
    "; @@ -86,9 +86,9 @@ $lang->loading = '稍候...'; $lang->notFound = '抱歉,您訪問的對象並不存在!'; $lang->showAll = '[[全部顯示]]'; -$lang->future = '未來'; -$lang->year = '年'; -$lang->workingHour = '工時'; +$lang->future = '未來'; +$lang->year = '年'; +$lang->workingHour = '工時'; $lang->idAB = 'ID'; $lang->priAB = 'P'; @@ -102,14 +102,17 @@ $lang->common->common = '公有模組'; /* 主導航菜單。*/ $lang->menu = new stdclass(); -$lang->menu->my = ' 我的地盤|my|index'; -$lang->menu->product = $lang->productCommon . '|product|index'; -$lang->menu->project = $lang->projectCommon . '|project|index'; -$lang->menu->qa = '測試|qa|index'; -$lang->menu->doc = '文檔|doc|index'; -$lang->menu->report = '統計|report|index'; -$lang->menu->company = '組織|company|index'; -$lang->menu->admin = '後台|admin|index'; +$lang->menu->my = ' 我的地盤|my|index'; +$lang->menu->product = $lang->productCommon . '|product|index'; +$lang->menu->project = $lang->projectCommon . '|project|index'; +$lang->menu->qa = '測試|qa|index'; +$lang->menu->doc = '文檔|doc|index'; +$lang->menu->report = '統計|report|index'; +$lang->menu->company = '組織|company|index'; + +$lang->adminMenu = '後台|admin|index'; + +$lang->dividerMenu = ',qa,'; /* 查詢條中可以選擇的對象列表。*/ $lang->searchObjects['bug'] = 'Bug'; @@ -145,12 +148,12 @@ $lang->exportTypeList['selected'] = '選中記錄'; $lang->lang = 'Language'; /* 風格列表。*/ -$lang->theme = '主題'; -$lang->themes['default'] = '預設'; -$lang->themes['green'] = '綠色'; -$lang->themes['red'] = '紅色'; -$lang->themes['lightblue'] = '亮藍'; -$lang->themes['blackberry'] = '黑莓'; +$lang->theme = '主題'; +$lang->themes['default'] = '預設'; +$lang->themes['green'] = '綠色'; +$lang->themes['red'] = '紅色'; +$lang->themes['lightblue'] = '亮藍'; +$lang->themes['blackberry'] = '黑莓'; /* 首頁菜單設置。*/ $lang->index = new stdclass(); @@ -163,7 +166,6 @@ $lang->index->menu->project = "瀏覽{$lang->projectCommon}|project|browse"; $lang->my = new stdclass(); $lang->my->menu = new stdclass(); -$lang->my->menu->account = array('link' => ' %s' . $lang->arrow . '', 'fixed' => true); $lang->my->menu->index = '首頁|my|index'; $lang->my->menu->todo = array('link' => '待辦|my|todo|', 'subModule' => 'todo'); $lang->my->menu->task = array('link' => '任務|my|task|', 'subModule' => 'task'); @@ -187,20 +189,20 @@ $lang->score->menu = $lang->my->menu; $lang->product = new stdclass(); $lang->product->menu = new stdclass(); -$lang->product->menu->list = array('link' => '%s', 'fixed' => true); -$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story'); -$lang->product->menu->dynamic = '動態|product|dynamic|productID=%s'; -$lang->product->menu->plan = array('link' => '計劃|productplan|browse|productID=%s', 'subModule' => 'productplan'); -$lang->product->menu->release = array('link' => '發佈|release|browse|productID=%s', 'subModule' => 'release'); -$lang->product->menu->roadmap = '路線圖|product|roadmap|productID=%s'; -$lang->product->menu->doc = array('link' => '文檔|doc|objectLibs|type=product&objectID=%s&from=product', 'subModule' => 'doc'); -$lang->product->menu->branch = '@branch@|branch|manage|productID=%s'; -$lang->product->menu->module = '模組|tree|browse|productID=%s&view=story'; -$lang->product->menu->view = array('link' => '概況|product|view|productID=%s', 'alias' => 'edit'); -$lang->product->menu->project = "{$lang->projectCommon}|product|project|status=all&productID=%s"; -$lang->product->menu->create = array('link' => " 添加{$lang->productCommon}|product|create", 'float' => 'right'); -$lang->product->menu->all = array('link' => " 所有{$lang->productCommon}|product|all|productID=%s", 'float' => 'right'); -$lang->product->menu->index = array('link' => "{$lang->productCommon}主頁|product|index|locate=no", 'float' => 'right'); +$lang->product->menu->list = array('link' => '%s', 'fixed' => true); +$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', 'subModule' => 'story'); +$lang->product->menu->dynamic = '動態|product|dynamic|productID=%s'; +$lang->product->menu->plan = array('link' => '計劃|productplan|browse|productID=%s', 'subModule' => 'productplan'); +$lang->product->menu->release = array('link' => '發佈|release|browse|productID=%s', 'subModule' => 'release'); +$lang->product->menu->roadmap = '路線圖|product|roadmap|productID=%s'; +$lang->product->menu->doc = array('link' => '文檔|doc|objectLibs|type=product&objectID=%s&from=product', 'subModule' => 'doc'); +$lang->product->menu->branch = '@branch@|branch|manage|productID=%s'; +$lang->product->menu->module = '模組|tree|browse|productID=%s&view=story'; +$lang->product->menu->view = array('link' => '概況|product|view|productID=%s', 'alias' => 'edit'); +$lang->product->menu->project = "{$lang->projectCommon}|product|project|status=all&productID=%s"; +$lang->product->menu->create = array('link' => " 添加{$lang->productCommon}|product|create", 'float' => 'right'); +$lang->product->menu->all = array('link' => " 所有{$lang->productCommon}|product|all|productID=%s", 'float' => 'right'); +$lang->product->menu->index = array('link' => "{$lang->productCommon}主頁|product|index|locate=no", 'float' => 'right'); $lang->story = new stdclass(); $lang->productplan = new stdclass(); @@ -216,20 +218,20 @@ $lang->release->menu = $lang->product->menu; $lang->project = new stdclass(); $lang->project->menu = new stdclass(); -$lang->project->menu->list = array('link' => '%s', 'fixed' => true); -$lang->project->menu->task = array('link' => '任務|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'grouptask,importtask,burn,importbug,kanban,printkanban,tree'); -$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory,storykanban'); -$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; -$lang->project->menu->dynamic = '動態|project|dynamic|projectID=%s'; -$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build'); -$lang->project->menu->testtask = array('link' => '測試單|project|testtask|projectID=%s'); -$lang->project->menu->team = array('link' => '團隊|project|team|projectID=%s', 'alias' => 'managemembers'); -$lang->project->menu->doc = array('link' => '文檔|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc'); -$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s'; -$lang->project->menu->view = array('link' => '概況|project|view|projectID=%s', 'alias' => 'edit,start,suspend,putoff,close'); -$lang->project->menu->create = array('link' => " 添加{$lang->projectCommon}|project|create", 'float' => 'right'); -$lang->project->menu->all = array('link' => " 所有{$lang->projectCommon}|project|all|status=undone&projectID=%s", 'float' => 'right'); -$lang->project->menu->index = array('link' => "{$lang->projectCommon}主頁|project|index|locate=no", 'float' => 'right'); +$lang->project->menu->list = array('link' => '%s', 'fixed' => true); +$lang->project->menu->task = array('link' => '任務|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'grouptask,importtask,burn,importbug,kanban,printkanban,tree'); +$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory,storykanban'); +$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; +$lang->project->menu->dynamic = '動態|project|dynamic|projectID=%s'; +$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build'); +$lang->project->menu->testtask = array('link' => '測試單|project|testtask|projectID=%s'); +$lang->project->menu->team = array('link' => '團隊|project|team|projectID=%s', 'alias' => 'managemembers'); +$lang->project->menu->doc = array('link' => '文檔|doc|objectLibs|type=project&objectID=%s&from=project', 'subModule' => 'doc'); +$lang->project->menu->product = $lang->productCommon . '|project|manageproducts|projectID=%s'; +$lang->project->menu->view = array('link' => '概況|project|view|projectID=%s', 'alias' => 'edit,start,suspend,putoff,close'); +$lang->project->menu->create = array('link' => " 添加{$lang->projectCommon}|project|create", 'float' => 'right'); +$lang->project->menu->all = array('link' => " 所有{$lang->projectCommon}|project|all|status=undone&projectID=%s", 'float' => 'right'); +$lang->project->menu->index = array('link' => "{$lang->projectCommon}主頁|project|index|locate=no", 'float' => 'right'); $lang->task = new stdclass(); $lang->build = new stdclass(); @@ -296,9 +298,9 @@ $lang->caselib->menu->index = array('link' => "測 $lang->doc = new stdclass(); $lang->doc->menu = new stdclass(); -$lang->doc->menu->list = array('link' => '%s', 'fixed' => true); -$lang->doc->menu->crumb = array('link' => '%s', 'fixed' => true); -$lang->doc->menu->create = array('link' => ' 添加文檔庫|doc|createLib', 'float' => 'right'); +$lang->doc->menu->list = array('link' => '%s', 'fixed' => true); +$lang->doc->menu->crumb = array('link' => '%s', 'fixed' => true); +$lang->doc->menu->create = array('link' => ' 添加文檔庫|doc|createLib', 'float' => 'right'); /* 統計視圖菜單設置。*/ $lang->report = new stdclass(); @@ -339,13 +341,12 @@ $lang->admin->menu = new stdclass(); $lang->admin->menu->index = array('link' => '首頁|admin|index', 'alias' => 'register,certifytemail,certifyztmobile,ztcompany'); $lang->admin->menu->extension = array('link' => '插件|extension|browse', 'subModule' => 'extension'); $lang->admin->menu->custom = array('link' => '自定義|custom|set', 'subModule' => 'custom'); -$lang->admin->menu->mail = array('link' => '發信|mail|index', 'subModule' => 'mail'); +$lang->admin->menu->message = array('link' => '消息|message|index', 'subModule' => 'message,mail,webhook'); $lang->admin->menu->backup = array('link' => '備份|backup|index', 'subModule' => 'backup'); $lang->admin->menu->safe = array('link' => '安全|admin|safe', 'alias' => 'checkweak'); $lang->admin->menu->cron = array('link' => '計劃任務|cron|index', 'subModule' => 'cron'); $lang->admin->menu->trashes = array('link' => '資源回收筒|action|trash', 'subModule' => 'action'); $lang->admin->menu->dev = array('link' => '二次開發|dev|api', 'alias' => 'db', 'subModule' => 'dev,editor'); -$lang->admin->menu->api = array('link' => '介面|webhook|browse', 'alias' => 'create,edit', 'subModule' => 'entry,webhook'); $lang->admin->menu->sso = '然之整合|admin|sso'; $lang->convert = new stdclass(); @@ -360,6 +361,7 @@ $lang->cron = new stdclass(); $lang->dev = new stdclass(); $lang->entry = new stdclass(); $lang->webhook = new stdclass(); +$lang->message = new stdclass(); $lang->search = new stdclass(); $lang->convert->menu = $lang->admin->menu; @@ -374,6 +376,7 @@ $lang->mail->menu = $lang->admin->menu; $lang->dev->menu = $lang->admin->menu; $lang->entry->menu = $lang->admin->menu; $lang->webhook->menu = $lang->admin->menu; +$lang->message->menu = $lang->admin->menu; /* 菜單分組。*/ $lang->menugroup = new stdclass(); @@ -407,6 +410,7 @@ $lang->menugroup->mail = 'admin'; $lang->menugroup->dev = 'admin'; $lang->menugroup->entry = 'admin'; $lang->menugroup->webhook = 'admin'; +$lang->menugroup->message = 'admin'; /* 錯誤提示信息。*/ $lang->error = new stdclass(); @@ -423,6 +427,7 @@ $lang->error->int = array("『%s』應當是數字。", "『%s』應 $lang->error->float = "『%s』應當是數字,可以是小數。"; $lang->error->email = "『%s』應當為合法的EMAIL。"; $lang->error->date = "『%s』應當為合法的日期。"; +$lang->error->datetime = "『%s』應當為合法的日期。"; $lang->error->code = "『%s』應當為字母或數字的組合。"; $lang->error->account = "『%s』應當為合法的用戶名。"; $lang->error->passwordsame = "兩次密碼應當相等。"; @@ -466,31 +471,32 @@ $lang->pager->previousPage = "上一頁"; $lang->pager->nextPage = "下一頁"; $lang->pager->summery = "第 %s-%s 項,共 %s 項"; -$lang->proVersion = "專業版   "; -$lang->downNotify = "下載桌面提醒"; +$lang->proVersion = "專業版   "; +$lang->downNotify = "下載桌面提醒"; +$lang->website = "http://www.zentao.net"; $lang->suhosinInfo = "警告:數據太多,請在php.ini中修改sohusin.post.max_vars和sohusin.request.max_vars(大於%s的數)。 保存並重新啟動apache或php-fpm,否則會造成部分數據無法保存。"; $lang->maxVarsInfo = "警告:數據太多,請在php.ini中修改max_input_vars(大於%s的數)。 保存並重新啟動apache或php-fpm,否則會造成部分數據無法保存。"; $lang->pasteTextInfo = "粘貼文本到文本域中,每行文字作為一條數據的標題。"; $lang->noticeImport = "

    導入數據中,含有已經存在系統的數據,請確認這些數據要覆蓋或者全新插入

    覆蓋 全新插入

    "; -$lang->noResultsMatch = "沒有匹配結果"; -$lang->searchMore = "搜索此關鍵字的更多結果:"; -$lang->chooseUsersToMail = "選擇要發信通知的用戶..."; -$lang->browserNotice = '你目前使用的瀏覽器可能無法得到最佳瀏覽效果,建議使用Chrome、火狐、IE9+、Opera、Safari瀏覽器。'; -$lang->noticePasteImg = "可以在編輯器直接貼圖。"; +$lang->noResultsMatch = "沒有匹配結果"; +$lang->searchMore = "搜索此關鍵字的更多結果:"; +$lang->chooseUsersToMail = "選擇要發信通知的用戶..."; +$lang->browserNotice = '你目前使用的瀏覽器可能無法得到最佳瀏覽效果,建議使用Chrome、火狐、IE9+、Opera、Safari瀏覽器。'; +$lang->noticePasteImg = "可以在編輯器直接貼圖。"; /* 時間格式設置。*/ -if(!defined('DT_DATETIME1')) define('DT_DATETIME1', 'Y-m-d H:i:s'); -if(!defined('DT_DATETIME2')) define('DT_DATETIME2', 'y-m-d H:i'); -if(!defined('DT_MONTHTIME1'))define('DT_MONTHTIME1', 'n/d H:i'); -if(!defined('DT_MONTHTIME2'))define('DT_MONTHTIME2', 'n月d日 H:i'); -if(!defined('DT_DATE1')) define('DT_DATE1', 'Y-m-d'); -if(!defined('DT_DATE2')) define('DT_DATE2', 'Ymd'); -if(!defined('DT_DATE3')) define('DT_DATE3', 'Y年m月d日'); -if(!defined('DT_DATE4')) define('DT_DATE4', 'n月j日'); -if(!defined('DT_TIME1')) define('DT_TIME1', 'H:i:s'); -if(!defined('DT_TIME2')) define('DT_TIME2', 'H:i'); +if(!defined('DT_DATETIME1')) define('DT_DATETIME1', 'Y-m-d H:i:s'); +if(!defined('DT_DATETIME2')) define('DT_DATETIME2', 'y-m-d H:i'); +if(!defined('DT_MONTHTIME1')) define('DT_MONTHTIME1', 'n/d H:i'); +if(!defined('DT_MONTHTIME2')) define('DT_MONTHTIME2', 'n月d日 H:i'); +if(!defined('DT_DATE1')) define('DT_DATE1', 'Y-m-d'); +if(!defined('DT_DATE2')) define('DT_DATE2', 'Ymd'); +if(!defined('DT_DATE3')) define('DT_DATE3', 'Y年m月d日'); +if(!defined('DT_DATE4')) define('DT_DATE4', 'n月j日'); +if(!defined('DT_TIME1')) define('DT_TIME1', 'H:i:s'); +if(!defined('DT_TIME2')) define('DT_TIME2', 'H:i'); /* datepicker 時間*/ $lang->datepicker = new stdclass(); @@ -608,7 +614,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyStory') /* Adjust sub menu of product module. */ unset($lang->product->menu->project); unset($lang->product->menu->doc); - + /* Rename product module. */ $lang->menu->product = "{$lang->productCommon}|product|index"; @@ -761,15 +767,15 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest') $lang->testtask->menu->report = array('link' => '報告|testreport|browse', 'alias' => 'view,create,edit'); $lang->testtask->menu->create = array('link' => " 提交測試|testtask|create|productID=%s", 'float' => 'right'); - $lang->testtask->menuOrder[5] = 'product'; - $lang->testtask->menuOrder[10] = 'scope'; - $lang->testtask->menuOrder[15] = 'wait'; - $lang->testtask->menuOrder[20] = 'doing'; - $lang->testtask->menuOrder[25] = 'blocked'; - $lang->testtask->menuOrder[30] = 'done'; - $lang->testtask->menuOrder[35] = 'totalStatus'; - $lang->testtask->menuOrder[40] = 'report'; - $lang->testtask->menuOrder[45] = 'create'; + $lang->testtask->menuOrder[5] = 'product'; + $lang->testtask->menuOrder[10] = 'scope'; + $lang->testtask->menuOrder[15] = 'wait'; + $lang->testtask->menuOrder[20] = 'doing'; + $lang->testtask->menuOrder[25] = 'blocked'; + $lang->testtask->menuOrder[30] = 'done'; + $lang->testtask->menuOrder[35] = 'totalStatus'; + $lang->testtask->menuOrder[40] = 'report'; + $lang->testtask->menuOrder[45] = 'create'; $lang->testreport->menu = $lang->testtask->menu; $lang->testreport->menuOrder = $lang->testtask->menuOrder; @@ -806,7 +812,7 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest') $lang->build->menu = $lang->product->menu; $lang->build->menuOrder = $lang->product->menuOrder; - + /* Adjust menu group. */ $lang->menugroup->bug = 'bug'; $lang->menugroup->testcase = 'testcase'; @@ -814,8 +820,8 @@ if(isset($config->global->flow) and $config->global->flow == 'onlyTest') $lang->menugroup->testsuite = 'testsuite'; $lang->menugroup->testreport = 'testtask'; $lang->menugroup->build = 'product'; - - /* Adjust search objects. */ + + /* Adjust search objects. */ unset($lang->searchObjects['story']); unset($lang->searchObjects['task']); unset($lang->searchObjects['release']); diff --git a/module/common/model.php b/module/common/model.php index 0208b25cfb..c53db915f2 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -228,7 +228,7 @@ class commonModel extends model * @access public * @return void */ - public static function printTopBar() + public static function printUserBar() { global $lang, $app; @@ -236,37 +236,44 @@ class commonModel extends model { $isGuest = $app->user->account == 'guest'; - echo "'; - + echo '
  • '; + echo '
  • '; if($isGuest) { echo html::a(helper::createLink('user', 'login'), $lang->login); @@ -275,19 +282,30 @@ class commonModel extends model { echo html::a(helper::createLink('user', 'logout'), $lang->logout); } + echo '
  • '; } + } - if($app->company->website) echo html::a($app->company->website, $lang->company->website, '_blank'); - if($app->company->backyard) echo html::a($app->company->backyard, $lang->company->backyard, '_blank'); - - echo ""; - echo html::a(helper::createLink('misc', 'about'), $lang->aboutZenTao, '', "class='about iframe' data-width='900' data-headerless='true' data-backdrop='true' data-keyboard='true' data-class='modal-about'"); + echo "\n"; + echo '
  • ' . html::a(helper::createLink('misc', 'about'), $lang->aboutZenTao, '', "class='about iframe' data-width='900' data-headerless='true' data-backdrop='true' data-keyboard='true' data-class='modal-about'") . '
  • '; + echo ''; } /** @@ -340,16 +358,19 @@ class commonModel extends model $menu = customModel::getMainMenu(); $activeName = 'active'; - echo "
    bug->linkBug;?>bug->linkBug;?> linkBugTitles)) diff --git a/module/build/lang/en.php b/module/build/lang/en.php index 8ddec86168..f5d21f084b 100644 --- a/module/build/lang/en.php +++ b/module/build/lang/en.php @@ -10,7 +10,7 @@ * @link http://www.zentao.net */ $lang->build->common = "Build"; -$lang->build->create = "Create"; +$lang->build->create = "Create Build"; $lang->build->edit = "Edit"; $lang->build->linkStory = "Link Story"; $lang->build->linkBug = "Link Bug"; @@ -44,7 +44,7 @@ $lang->build->unlinkStory = 'Unlink Story'; $lang->build->unlinkBug = 'Unlink Bug'; $lang->build->stories = 'Finished Story'; $lang->build->bugs = 'Resolved Bug'; -$lang->build->generatedBugs = 'Remained Bug'; +$lang->build->generatedBugs = 'Left Bug'; $lang->build->noProduct = " This {$lang->projectCommon} has not linked to {$lang->productCommon}, so Build cannot be created. Please first link {$lang->productCommon}"; $lang->build->finishStories = ' %s Story(ies) have been finished.'; diff --git a/module/build/model.php b/module/build/model.php index 33dea5c83d..f40a24ddf4 100644 --- a/module/build/model.php +++ b/module/build/model.php @@ -15,8 +15,8 @@ class buildModel extends model { /** * Get build info. - * - * @param int $buildID + * + * @param int $buildID * @param bool $setImgSize * @access public * @return object @@ -39,8 +39,8 @@ class buildModel extends model /** * Get by ID list. - * - * @param array $idList + * + * @param array $idList * @access public * @return array */ @@ -51,8 +51,8 @@ class buildModel extends model /** * Get builds of a project. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return array */ @@ -70,10 +70,10 @@ class buildModel extends model } /** - * Get builds of a project in pairs. - * - * @param int $projectID - * @param int $productID + * Get builds of a project in pairs. + * + * @param int $projectID + * @param int $productID * @param string $params noempty|notrunk, can be a set of them * @access public * @return array @@ -122,25 +122,22 @@ class buildModel extends model * @param int $branch * @param string $params noempty|notrunk, can be a set of them * @param bool $replace - * @param int $project * * @access public * @return array */ - public function getProductBuildPairs($products, $branch = 0, $params = 'noterminate, nodone', $replace = true, $project = 0) + public function getProductBuildPairs($products, $branch = 0, $params = 'noterminate, nodone', $replace = true) { $sysBuilds = array(); if(strpos($params, 'noempty') === false) $sysBuilds = array('' => ''); if(strpos($params, 'notrunk') === false) $sysBuilds = $sysBuilds + array('trunk' => $this->lang->trunk); - /* Add project for Bug#1344. */ $productBuilds = $this->dao->select('t1.id, t1.name, t1.project, t2.status as projectStatus, t3.id as releaseID, t3.status as releaseStatus, t4.name as branchName')->from(TABLE_BUILD)->alias('t1') ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') ->leftJoin(TABLE_RELEASE)->alias('t3')->on('t1.id = t3.build') ->leftJoin(TABLE_BRANCH)->alias('t4')->on('t1.branch = t4.id') ->where('t1.product')->in($products) ->beginIF($branch)->andWhere('t1.branch')->in("0,$branch")->fi() - ->beginIF($project)->andWhere('t1.project')->eq($project)->fi() ->andWhere('t1.deleted')->eq(0) ->orderBy('t1.date desc, t1.id desc')->fetchAll('id'); @@ -172,14 +169,14 @@ class buildModel extends model /** * Get last build. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return bool | object */ public function getLast($projectID) { - return $this->dao->select('id, name')->from(TABLE_BUILD) + return $this->dao->select('id, name')->from(TABLE_BUILD) ->where('project')->eq((int)$projectID) ->orderBy('date DESC,id DESC') ->limit(1) @@ -188,8 +185,8 @@ class buildModel extends model /** * Create a build - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -226,8 +223,8 @@ class buildModel extends model /** * Update a build. - * - * @param int $buildID + * + * @param int $buildID * @access public * @return void */ @@ -256,8 +253,8 @@ class buildModel extends model /** * Update linked bug to resolved. - * - * @param object $build + * + * @param object $build * @access public * @return void */ @@ -299,8 +296,8 @@ class buildModel extends model /** * Link stories - * - * @param int $buildID + * + * @param int $buildID * @access public * @return void */ @@ -317,10 +314,10 @@ class buildModel extends model } /** - * Unlink story - * - * @param int $buildID - * @param int $storyID + * Unlink story + * + * @param int $buildID + * @param int $storyID * @access public * @return void */ @@ -334,8 +331,8 @@ class buildModel extends model /** * Batch unlink story. - * - * @param int $buildID + * + * @param int $buildID * @access public * @return void */ @@ -357,8 +354,8 @@ class buildModel extends model /** * Link bugs. - * - * @param int $buildID + * + * @param int $buildID * @access public * @return void */ @@ -376,10 +373,10 @@ class buildModel extends model } /** - * Unlink bug. - * - * @param int $buildID - * @param int $bugID + * Unlink bug. + * + * @param int $buildID + * @param int $bugID * @access public * @return void */ @@ -393,8 +390,8 @@ class buildModel extends model /** * Batch unlink bug. - * - * @param int $buildID + * + * @param int $buildID * @access public * @return void */ diff --git a/module/build/view/linkstory.html.php b/module/build/view/linkstory.html.php index e62a058945..cb56ed2cf9 100644 --- a/module/build/view/linkstory.html.php +++ b/module/build/view/linkstory.html.php @@ -26,9 +26,9 @@ include '../../common/view/tablesorter.html.php'; story->title;?> openedByAB;?> assignedToAB;?> story->estimateAB;?> story->estimateAB;?> statusAB;?> story->stageAB;?> story->stageAB;?>
    story->estimateAB);?> statusAB);?> story->stageAB);?> actions?> actions?>
    bug->openedDateAB);?> bug->resolvedByAB);?> bug->resolvedDateAB);?> actions?> actions?>
    - + diff --git a/module/company/view/view.html.php b/module/company/view/view.html.php index cad834d888..2694dec2f0 100644 --- a/module/company/view/view.html.php +++ b/module/company/view/view.html.php @@ -20,7 +20,7 @@
    company->name;?>company->name;?> name, "class='form-control' autocomplete='off'");?>
    - + diff --git a/module/convert/converter/redmine1.1.php b/module/convert/converter/redmine1.1.php index 0d7c93071a..563a1f5026 100644 --- a/module/convert/converter/redmine1.1.php +++ b/module/convert/converter/redmine1.1.php @@ -34,7 +34,7 @@ class redmine11ConvertModel extends redmineConvertModel } /** * Execute the converter. - * + * * @access public * @return array */ @@ -74,11 +74,11 @@ class redmine11ConvertModel extends redmineConvertModel $result['docs'] = self::$convertDocCount; $result['files'] = self::$convertFileCount; return $result; - } - - /** - * Set table names. - * + } + + /** + * Set table names. + * * @access public * @return void */ @@ -137,9 +137,9 @@ class redmine11ConvertModel extends redmineConvertModel /** * Convert groups. - * + * * @access public - * @return void + * @return void */ public function convertGroup() { @@ -176,9 +176,9 @@ class redmine11ConvertModel extends redmineConvertModel /** * Convert users. - * + * * @access public - * @return void + * @return void */ public function convertUser() { @@ -217,8 +217,8 @@ class redmine11ConvertModel extends redmineConvertModel } /** - * convert relationship between user and group. - * + * convert relationship between user and group. + * * @access public * @return void */ @@ -255,10 +255,10 @@ class redmine11ConvertModel extends redmineConvertModel } /** - * convert products. - * + * convert products. + * * @access public - * @return void + * @return void */ public function convertProduct() { @@ -280,9 +280,9 @@ class redmine11ConvertModel extends redmineConvertModel /** * Convert projects. - * + * * @access public - * @return void + * @return void */ public function convertProject() { @@ -313,12 +313,12 @@ class redmine11ConvertModel extends redmineConvertModel $convertCount = count($projects) + count($this->map['projectOfProduct']); self::$convertProjectCount += $convertCount; } - + /** - * convert builds and releases - * + * convert builds and releases + * * @access public - * @return void + * @return void */ public function convertBuildAndRelease() { @@ -370,10 +370,10 @@ class redmine11ConvertModel extends redmineConvertModel } /** - * convert productPlans - * + * convert productPlans + * * @access public - * @return void + * @return void */ public function convertProductPlan() { @@ -401,11 +401,11 @@ class redmine11ConvertModel extends redmineConvertModel } $convertCount = count($this->map['products']) + count($productPlans); self::$convertProductPlanCount += $convertCount; - } + } /** - * convert relationship between project and product. - * + * convert relationship between project and product. + * * @access public * @return void */ @@ -424,8 +424,8 @@ class redmine11ConvertModel extends redmineConvertModel } /** - * convert teams. - * + * convert teams. + * * @access public * @return void */ @@ -454,10 +454,10 @@ class redmine11ConvertModel extends redmineConvertModel } /** - * convert docLibs. - * + * convert docLibs. + * * @access public - * @return void + * @return void */ public function convertDocLib() { @@ -478,10 +478,10 @@ class redmine11ConvertModel extends redmineConvertModel } /** - * convert docs. - * + * convert docs. + * * @access public - * @return void + * @return void */ public function convertDoc() { @@ -507,10 +507,10 @@ class redmine11ConvertModel extends redmineConvertModel } /** - * convert news. - * + * convert news. + * * @access public - * @return void + * @return void */ public function convertNews() { @@ -541,12 +541,12 @@ class redmine11ConvertModel extends redmineConvertModel } /** - * convert issue - * + * convert issue + * * @param array $aimTypes //aimTypes['issueTypeID'] = aimtype eg. aimTypes[1] = 'bug'; * @param array $statusTypes //statusTypes['task']['statusTypeID'] = statusType eg. statusTypes['task'][1] = 'wait'; * //statusTypes['bug']['statusTypeID'] = statusType eg. statusTypes['bug'][1] = 'active'; - * @param array $priTypes //priTypes['task']['priTypeID'] = priType; eg. priTypes['task'][1] = 1; + * @param array $priTypes //priTypes['task']['priTypeID'] = priType; eg. priTypes['task'][1] = 1; * @access public * @return void */ @@ -574,13 +574,13 @@ class redmine11ConvertModel extends redmineConvertModel } /** - * convert story - * - * @param array $issueType - * @param array $statusTypes - * @param array $priTypes + * convert story + * + * @param array $issueType + * @param array $statusTypes + * @param array $priTypes * @access public - * @return void + * @return void */ public function convertStory($issueType, $statusTypes, $priTypes) { @@ -623,13 +623,13 @@ class redmine11ConvertModel extends redmineConvertModel } /** - * convert task - * - * @param array $issueType - * @param array $statusTypes - * @param array $priTypes + * convert task + * + * @param array $issueType + * @param array $statusTypes + * @param array $priTypes * @access public - * @return void + * @return void */ public function convertTask($issueType, $statusTypes, $priTypes) { @@ -651,7 +651,7 @@ class redmine11ConvertModel extends redmineConvertModel $task->pri = $priTypes['task'][$task->pri]; $task->status = $statusTypes['task'][$task->status]; if($task->project == 0) - { + { $task->project = $this->map['projectOfProduct'][$task->product]; } else @@ -668,13 +668,13 @@ class redmine11ConvertModel extends redmineConvertModel } /** - * convert bug - * - * @param array $issueType - * @param array $statusTypes - * @param array $priTypes + * convert bug + * + * @param array $issueType + * @param array $statusTypes + * @param array $priTypes * @access public - * @return void + * @return void */ public function convertBug($issueType, $statusTypes, $priTypes) { @@ -704,7 +704,7 @@ class redmine11ConvertModel extends redmineConvertModel $bug->caseVersion = 1; $bug->result = 0; if($bug->project == 0) - { + { $bug->project = $this->map['projectOfProduct'][$bug->product]; } else @@ -712,7 +712,7 @@ class redmine11ConvertModel extends redmineConvertModel $bug->project = $this->map['project'][$bug->project]; } unset($bug->id); - $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec(); + $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec(); $this->map['issueID'][$issueID] = $this->dao->lastInsertID(); $this->map['issueType'][$issueID] = 'bug'; } @@ -721,9 +721,9 @@ class redmine11ConvertModel extends redmineConvertModel /** * Convert attachments. - * + * * @access public - * @return void + * @return void */ public function convertFile() { @@ -752,7 +752,7 @@ class redmine11ConvertModel extends redmineConvertModel /* Transform objectType and objectID */ if($file->objectType == 'Issue') { - $file->objectType = $this->map['issueType'][$file->objectID]; + $file->objectType = $this->map['issueType'][$file->objectID]; $file->objectID = $this->map['issueID'][$file->objectID]; } elseif($file->objectType == 'Document') @@ -808,7 +808,7 @@ class redmine11ConvertModel extends redmineConvertModel /** * Clear the converted records. - * + * * @access public * @return void */ diff --git a/module/cron/lang/en.php b/module/cron/lang/en.php index 9e60f3d542..23dd843cb6 100644 --- a/module/cron/lang/en.php +++ b/module/cron/lang/en.php @@ -1,5 +1,5 @@ cron->common = 'Cron'; +$lang->cron->common = 'Scheduled Task'; $lang->cron->index = 'Home'; $lang->cron->list = 'Tasks'; $lang->cron->create = 'Add'; @@ -21,7 +21,7 @@ $lang->cron->remark = 'Remark'; $lang->cron->lastTime = 'Last Executed'; $lang->cron->turnonList['1'] = 'On'; -$lang->cron->turnonList['0'] = 'Off'; +$lang->cron->turnonList['0'] = 'Shutdown'; $lang->cron->statusList['normal'] = 'Normal'; $lang->cron->statusList['running'] = 'Running'; @@ -33,14 +33,14 @@ $lang->cron->typeList['system'] = 'System Command'; $lang->cron->toggleList['start'] = 'Activate'; $lang->cron->toggleList['stop'] = 'Deactivate'; -$lang->cron->confirmDelete = 'Do you want to delete the Planned Task?'; +$lang->cron->confirmDelete = 'Do you want to delete the Scheduled Task?'; $lang->cron->confirmTurnon = 'Do you want to truncoff the Cron?'; $lang->cron->introduction = <<Planned Task can do scheduled execution, such as update burndown chart, backup, etc.

    +

    Scheduled Task can do scheduled execution, such as update burndown chart, backup, etc.

    This function need to be improved, so it is turned off by default.

    EOD; $lang->cron->confirmOpen = <<Do you want to turn it on?Turn On Planned Task

    +

    Do you want to turn it on?Turn On Scheduled Task

    EOD; $lang->cron->notice = new stdclass(); @@ -49,5 +49,5 @@ $lang->cron->notice->h = 'Range:0-23'; $lang->cron->notice->dom = 'Range:1-31'; $lang->cron->notice->mon = 'Range:1-12'; $lang->cron->notice->dow = 'Range:0-6'; -$lang->cron->notice->help = 'Note:If the server is restarted, or Planned Task is not working, it means Planned Task has stopped working. You have to click 【Create】 or refresh the page to start the Planned Task. If the last execution time in Task List has changed, it means the Task is started.'; +$lang->cron->notice->help = 'Note:If server restarted, or Scheduled Task is not working, it means Scheduled Task has stopped. You can restart it by clicking 【Restart】 or reload this page. If the last execution time in changed, it means the Task is running.'; $lang->cron->notice->errorRule = '"%s" is not valid'; diff --git a/module/cron/view/index.html.php b/module/cron/view/index.html.php index 901c8a0f45..88fd9a75a6 100644 --- a/module/cron/view/index.html.php +++ b/module/cron/view/index.html.php @@ -30,13 +30,13 @@
    company->name;?>company->name;?> name;?>
    - - - - - + + + + + - + diff --git a/module/custom/control.php b/module/custom/control.php index 07e09e6b71..353a7f6a5c 100644 --- a/module/custom/control.php +++ b/module/custom/control.php @@ -81,7 +81,12 @@ class custom extends control if(strtolower($_SERVER['REQUEST_METHOD']) == "post") { - if(($module == 'story' or $module == 'testcase') and $field == 'review') + if($module == 'story' and $field == 'review') + { + $data = fixer::input('post')->join('forceReview', ',')->get(); + $this->loadModel('setting')->setItems("system.$module", $data); + } + elseif($module == 'testcase' and $field == 'review') { $review = fixer::input('post')->get(); if($review->needReview) $data = fixer::input('post')->join('forceNotReview', ',')->remove('forceReview')->get(); diff --git a/module/custom/lang/en.php b/module/custom/lang/en.php index 07ab03f68a..7bea454f8b 100644 --- a/module/custom/lang/en.php +++ b/module/custom/lang/en.php @@ -5,9 +5,9 @@ $lang->custom->set = 'Customize'; $lang->custom->restore = 'Reset to Default'; $lang->custom->key = 'Key'; $lang->custom->value = 'Value'; -$lang->custom->flow = 'Process'; -$lang->custom->working = 'Working'; -$lang->custom->select = 'Select Process'; +$lang->custom->flow = 'Workflow'; +$lang->custom->working = 'WorkStyle'; +$lang->custom->select = 'Select Workflow'; $lang->custom->branch = 'Multi Branch'; $lang->custom->owner = 'Owner'; $lang->custom->module = 'Module'; @@ -23,35 +23,35 @@ $lang->custom->object['task'] = 'Task'; $lang->custom->object['bug'] = 'Bug'; $lang->custom->object['testcase'] = 'Case'; $lang->custom->object['testtask'] = 'Build'; -$lang->custom->object['todo'] = 'To-Dos'; +$lang->custom->object['todo'] = 'Todo'; $lang->custom->object['user'] = 'User'; -$lang->custom->object['block'] = 'Block'; +$lang->custom->object['block'] = 'ClosedBlock'; $lang->custom->story = new stdClass(); $lang->custom->story->fields['priList'] = 'Priority'; $lang->custom->story->fields['sourceList'] = 'Source'; -$lang->custom->story->fields['reasonList'] = 'Reason'; +$lang->custom->story->fields['reasonList'] = 'Close Reason'; $lang->custom->story->fields['stageList'] = 'Stage'; $lang->custom->story->fields['statusList'] = 'Status'; -$lang->custom->story->fields['reviewResultList'] = 'Result'; -$lang->custom->story->fields['review'] = 'Review'; +$lang->custom->story->fields['reviewResultList'] = 'Review Result'; +$lang->custom->story->fields['review'] = 'Review Required'; $lang->custom->task = new stdClass(); $lang->custom->task->fields['priList'] = 'Priority'; $lang->custom->task->fields['typeList'] = 'Type'; -$lang->custom->task->fields['reasonList'] = 'Reason'; +$lang->custom->task->fields['reasonList'] = 'Close Reason'; $lang->custom->task->fields['statusList'] = 'Status'; -$lang->custom->task->fields['hours'] = 'Working hours'; +$lang->custom->task->fields['hours'] = 'Man-hours'; $lang->custom->bug = new stdClass(); $lang->custom->bug->fields['priList'] = 'Priority'; -$lang->custom->bug->fields['severityList'] = 'Priority'; +$lang->custom->bug->fields['severityList'] = 'Severity'; $lang->custom->bug->fields['osList'] = 'OS'; $lang->custom->bug->fields['browserList'] = 'Browser'; $lang->custom->bug->fields['typeList'] = 'Type'; $lang->custom->bug->fields['resolutionList'] = 'Solution'; $lang->custom->bug->fields['statusList'] = 'Status'; -$lang->custom->bug->fields['longlife'] = 'Long Life Days'; +$lang->custom->bug->fields['longlife'] = 'Shelved Days'; $lang->custom->testcase = new stdClass(); $lang->custom->testcase->fields['priList'] = 'Priority'; @@ -59,7 +59,7 @@ $lang->custom->testcase->fields['typeList'] = 'Type'; $lang->custom->testcase->fields['stageList'] = 'Stage'; $lang->custom->testcase->fields['resultList'] = 'Result'; $lang->custom->testcase->fields['statusList'] = 'Status'; -$lang->custom->testcase->fields['review'] = 'Review'; +$lang->custom->testcase->fields['review'] = 'Review Required'; $lang->custom->testtask = new stdClass(); $lang->custom->testtask->fields['priList'] = 'Priority'; @@ -84,10 +84,10 @@ $lang->custom->confirmRestore = 'Do you want to reset to Default?'; $lang->custom->notice = new stdclass(); $lang->custom->notice->userRole = 'Key must be no more than 20 characters!'; -$lang->custom->notice->canNotAdd = 'This item will be processed, so customized feature is not enabled.'; -$lang->custom->notice->forceReview = 'Review is required for %s submitted by certain assignee.'; -$lang->custom->notice->forceNotReview = "Not review is required for %s submitted by certain assignee."; -$lang->custom->notice->longlife = 'List "Undone" bugs that are older than hold days from "Longlife" bugs.'; +$lang->custom->notice->canNotAdd = 'These items are parameters of calculation, so customized creation is not enabled.'; +$lang->custom->notice->forceReview = '%s Review is required for certain submitters.'; +$lang->custom->notice->forceNotReview = "%s Review is NOT required for certain submitters."; +$lang->custom->notice->longlife = 'Define shelved bugs.'; $lang->custom->notice->priListKey = 'Priority list key should be numbers!'; $lang->custom->notice->keyList = 'key should be English or digital!'; $lang->custom->notice->severityListKey = 'Bug severity list key should be numbers.'; @@ -96,7 +96,7 @@ $lang->custom->notice->indexPage['project'] = "ZenTao 8.2+ has Project Homepage. $lang->custom->notice->indexPage['qa'] = "ZenTao 8.2+ has QA Homepage. Do you want to go to QA Homepage?"; $lang->custom->storyReview = 'Review'; -$lang->custom->forceReview = 'Review Required'; +$lang->custom->forceReview = 'Selective Review'; $lang->custom->forceNotReview = 'No review'; $lang->custom->reviewList[1] = 'On'; $lang->custom->reviewList[0] = 'Off'; @@ -116,10 +116,10 @@ $lang->custom->productProject->relation['1_1'] = 'Project - Sprint'; $lang->custom->productProject->notice = 'Please select according to your team.'; -$lang->custom->workingList['full'] = 'Full'; -$lang->custom->workingList['onlyTest'] = 'Test'; -$lang->custom->workingList['onlyStory'] = 'Story'; -$lang->custom->workingList['onlyTask'] = 'Task'; +$lang->custom->workingList['full'] = 'Full Management of Dev'; +$lang->custom->workingList['onlyTest'] = 'Test Management'; +$lang->custom->workingList['onlyStory'] = 'Story Management'; +$lang->custom->workingList['onlyTask'] = 'Task Management'; $lang->custom->menuTip = 'Click to show/hide navigation bar. Drag to swtich display order.'; $lang->custom->saveFail = 'Failed to save!'; diff --git a/module/custom/view/set.html.php b/module/custom/view/set.html.php index 726474c997..6176e3fa87 100644 --- a/module/custom/view/set.html.php +++ b/module/custom/view/set.html.php @@ -50,20 +50,20 @@ EOT;
    cron->m?>cron->h?>cron->dom?>cron->mon?>cron->dow?>cron->m?>cron->h?>cron->dom?>cron->mon?>cron->dow?> cron->command?>cron->remark?>cron->remark?> cron->lastTime?> cron->status?> actions;?>
    - + - + > - + > - + @@ -115,7 +115,7 @@ EOT;
    custom->storyReview;?>custom->storyReview;?> custom->reviewList, $needReview);?>
    custom->forceReview;?> custom->notice->forceReview, $lang->$module->common);?>custom->notice->forceReview, $lang->$module->common);?>
    custom->forceNotReview;?> custom->notice->forceNotReview, $lang->$module->common);?>custom->notice->forceNotReview, $lang->$module->common);?>
    - + diff --git a/module/datatable/lang/en.php b/module/datatable/lang/en.php index 099a89c79e..27e72fcff3 100644 --- a/module/datatable/lang/en.php +++ b/module/datatable/lang/en.php @@ -8,8 +8,8 @@ $lang->datatable->reset = 'Reset'; $lang->datatable->custom = 'Custom Columns'; $lang->datatable->customTip = 'Check Columns to Display'; -$lang->datatable->switchToTable = 'Switch to Table'; -$lang->datatable->switchToDatatable = 'Switch to Datatable'; +$lang->datatable->switchToTable = 'Switch to Common Table'; +$lang->datatable->switchToDatatable = 'Switch to Advanced Table'; $lang->datatable->required = 'Required'; $lang->datatable->confirmReset = 'Do you want to restore the default settings?'; $lang->datatable->setGlobal = 'Global'; @@ -18,7 +18,7 @@ $lang->datatable->resetGlobal = 'Reset Global Default'; $lang->datatable->branch = 'Branch'; $lang->datatable->platform = 'Platform'; -$lang->datatable->showModule = 'Show/Hide Module Name'; +$lang->datatable->showModule = 'Show/Hide module name'; $lang->datatable->showModuleList[] = 'N/A'; $lang->datatable->showModuleList['base'] = 'Base Node'; $lang->datatable->showModuleList['end'] = 'End Node'; diff --git a/module/datatable/model.php b/module/datatable/model.php index afd6e2f33c..577ad6b7a2 100644 --- a/module/datatable/model.php +++ b/module/datatable/model.php @@ -127,10 +127,11 @@ class datatableModel extends model { $fixed = $col->fixed == 'no' ? 'true': 'false'; $width = is_numeric($col->width) ? "{$col->width}px" : $col->width; - $sorter = (isset($col->sort) and $col->sort == 'no') ? '' : '{sorter:false}'; $title = isset($col->name) ? "title='$col->name'" : ''; + if($id == 'id' and (int)$width < 90) $width = '90px'; + $width = $id != 'actions' ? "data-width='$width' style='width:$width'" : ''; - echo "'; diff --git a/module/datatable/view/ajaxcustom.html.php b/module/datatable/view/ajaxcustom.html.php index 03b8a8327e..c27d2484c9 100644 --- a/module/datatable/view/ajaxcustom.html.php +++ b/module/datatable/view/ajaxcustom.html.php @@ -60,12 +60,12 @@ $autoWidth = $col['width'] == 'auto'; ?>
    ' data-key='' data-fixed='' data-width=''> -   ({$lang->datatable->required})"?>
    datatable->width?> '>
    +   ({$lang->datatable->required})"?>
    diff --git a/module/dept/lang/en.php b/module/dept/lang/en.php index 3b8801e1a4..b35d0c2bb6 100644 --- a/module/dept/lang/en.php +++ b/module/dept/lang/en.php @@ -10,15 +10,15 @@ * @link http://www.zentao.net */ $lang->dept->common = 'Department'; -$lang->dept->manageChild = "Children"; +$lang->dept->manageChild = "Child Department"; $lang->dept->edit = "Edit"; $lang->dept->delete = "Delete"; $lang->dept->parent = "Parent"; $lang->dept->manager = "Manager"; $lang->dept->name = "Dept Name"; -$lang->dept->browse = "Departments"; +$lang->dept->browse = "Manage"; $lang->dept->manage = "Maintain Dept"; -$lang->dept->updateOrder = "Update/Order"; +$lang->dept->updateOrder = "Sort"; $lang->dept->add = "Add Dept"; $lang->dept->dragAndSort = "Drag and Sort"; diff --git a/module/dev/lang/en.php b/module/dev/lang/en.php index c50930a5c1..92ac52554e 100644 --- a/module/dev/lang/en.php +++ b/module/dev/lang/en.php @@ -53,7 +53,7 @@ $lang->dev->tableList['team'] = 'Team'; $lang->dev->tableList['testresult'] = 'Testing Result'; $lang->dev->tableList['testrun'] = 'Run Testing '; $lang->dev->tableList['testtask'] = 'Test Task'; -$lang->dev->tableList['todo'] = 'To-Do'; +$lang->dev->tableList['todo'] = 'Todo'; $lang->dev->tableList['user'] = 'User'; $lang->dev->tableList['usercontact'] = 'User Contact'; $lang->dev->tableList['usergroup'] = 'User Group'; @@ -93,6 +93,8 @@ $lang->dev->tableList['suitecase'] = 'Suite Case'; $lang->dev->tableList['score'] = 'Score'; $lang->dev->tableList['entry'] = 'Entry'; $lang->dev->tableList['webhook'] = 'WebHook'; +$lang->dev->tableList['webhookdatas'] = 'WebHookDatas'; +$lang->dev->tableList['log'] = 'Log'; $lang->dev->groupList['my'] = 'Dashboard'; $lang->dev->groupList['product'] = $lang->productCommon; diff --git a/module/dev/lang/zh-cn.php b/module/dev/lang/zh-cn.php index dc44c5b126..fc9ae49d9b 100644 --- a/module/dev/lang/zh-cn.php +++ b/module/dev/lang/zh-cn.php @@ -93,6 +93,8 @@ $lang->dev->tableList['suitecase'] = '套件用例'; $lang->dev->tableList['score'] = '积分'; $lang->dev->tableList['entry'] = '应用'; $lang->dev->tableList['webhook'] = 'WebHook'; +$lang->dev->tableList['webhookdatas'] = 'WebHook数据'; +$lang->dev->tableList['log'] = '接口日志'; $lang->dev->groupList['my'] = '我的地盘'; $lang->dev->groupList['product'] = $lang->productCommon; diff --git a/module/dev/lang/zh-tw.php b/module/dev/lang/zh-tw.php index 8652c239a8..a0d2f6394c 100644 --- a/module/dev/lang/zh-tw.php +++ b/module/dev/lang/zh-tw.php @@ -90,6 +90,11 @@ $lang->dev->tableList['doccontent'] = '文檔內容'; $lang->dev->tableList['storystage'] = '需求階段'; $lang->dev->tableList['tutorial'] = '新手教程'; $lang->dev->tableList['suitecase'] = '套件用例'; +$lang->dev->tableList['score'] = '積分'; +$lang->dev->tableList['entry'] = '應用'; +$lang->dev->tableList['webhook'] = 'WebHook'; +$lang->dev->tableList['webhookdatas'] = 'WebHook數據'; +$lang->dev->tableList['log'] = '介面日誌'; $lang->dev->groupList['my'] = '我的地盤'; $lang->dev->groupList['product'] = $lang->productCommon; diff --git a/module/dev/model.php b/module/dev/model.php index 7bbdd1ab47..f4049a8f0a 100644 --- a/module/dev/model.php +++ b/module/dev/model.php @@ -16,7 +16,7 @@ class devModel extends model foreach($datatables as $table) { $table = current($table); - if(strpos($table, $this->config->db->prefix) !== false) + if(empty($this->config->db->prefix) or strpos($table, $this->config->db->prefix) !== false) { $subTable = substr($table, strpos($table, '_') + 1); $group = zget($this->config->dev->group, $subTable, 'other'); diff --git a/module/doc/control.php b/module/doc/control.php index 0523918d42..3a577564e6 100644 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -601,13 +601,16 @@ class doc extends control * @access public * @return void */ - public function showFiles($type, $objectID, $viewType='card', $orderBy='t1.id_desc', $recTotal=0, $recPerPage=20, $pageID=1) + public function showFiles($type, $objectID, $viewType = '', $orderBy = 't1.id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { $uri = $this->app->getURI(true); $this->app->session->set('taskList', $uri); $this->app->session->set('storyList', $uri); $this->app->session->set('docList', $uri); + if(empty($viewType)) $viewType = !empty($_COOKIE['docFilesViewType']) ? $this->cookie->docFilesViewType : 'card'; + setcookie('docFilesViewType', $viewType, $this->config->cookieLife, $this->config->webRoot); + $table = $type == 'product' ? TABLE_PRODUCT : TABLE_PROJECT; $object = $this->dao->select('id,name')->from($table)->where('id')->eq($objectID)->fetch(); @@ -658,6 +661,7 @@ class doc extends control $this->view->type = $type; $this->view->object = $object; $this->view->files = $this->doc->getLibFiles($type, $objectID, $orderBy, $pager); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); $this->view->pager = $pager; $this->view->viewType = $viewType; $this->view->orderBy = $orderBy; diff --git a/module/doc/css/view.css b/module/doc/css/view.css index 66d52c908e..d15fdf60ef 100644 --- a/module/doc/css/view.css +++ b/module/doc/css/view.css @@ -6,3 +6,4 @@ fieldset > .content table tr th { border-top: 1px solid #BBB; background-color: #F7F7F7; } fieldset > .content table tr th, fieldset > .content table tr td{ padding: 5px 10px; } +.col-main{width:100%} diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 3d17d4127c..66d46a32dc 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -24,10 +24,10 @@ $lang->doc->content = 'Text'; $lang->doc->keywords = 'Keywords'; $lang->doc->url = 'URL'; $lang->doc->files = 'File'; -$lang->doc->addedBy = 'Added By'; -$lang->doc->addedDate = 'Added Date'; -$lang->doc->editedBy = 'Edited By'; -$lang->doc->editedDate = 'Edited Date'; +$lang->doc->addedBy = 'Creator'; +$lang->doc->addedDate = 'Create Date'; +$lang->doc->editedBy = 'Edit By'; +$lang->doc->editedDate = 'Edit Date'; $lang->doc->version = 'Version'; $lang->doc->basicInfo = 'Basic Info'; $lang->doc->deleted = 'Deleted'; @@ -45,22 +45,22 @@ $lang->doc->groups = 'Groups'; $lang->doc->users = 'Users'; $lang->doc->moduleDoc = 'By Module'; -$lang->doc->searchDoc = 'By Search'; +$lang->doc->searchDoc = 'Search'; $lang->doc->allDoc = 'All'; -$lang->doc->openedByMe = 'Opened By Me'; +$lang->doc->openedByMe = 'My'; $lang->doc->orderByOpen = 'Recently Added'; $lang->doc->orderByEdit = 'Recently Modifie'; /* 方法列表。*/ $lang->doc->index = 'Home'; -$lang->doc->create = 'Create'; +$lang->doc->create = 'Create Doc'; $lang->doc->edit = 'Edit'; $lang->doc->delete = 'Delete'; $lang->doc->browse = 'List'; $lang->doc->view = 'Details'; $lang->doc->diff = 'Diff'; $lang->doc->sort = 'Sort'; -$lang->doc->manageType = 'Manage Category'; +$lang->doc->manageType = 'Manage category'; $lang->doc->editType = 'Edit'; $lang->doc->deleteType = 'Delete'; $lang->doc->addType = 'Add'; @@ -74,8 +74,8 @@ $lang->doc->createLib = 'Create Library'; $lang->doc->allLibs = 'Libraries'; $lang->doc->objectLibs = "{$lang->productCommon}/{$lang->projectCommon} Library List"; $lang->doc->showFiles = 'File Library'; -$lang->doc->editLib = 'Edit'; -$lang->doc->deleteLib = 'Delete'; +$lang->doc->editLib = 'Edit Library'; +$lang->doc->deleteLib = 'Delete Library'; $lang->doc->fixedMenu = 'Fixed In Menu'; $lang->doc->removeMenu = 'Remove From Menu'; $lang->doc->search = 'Search'; @@ -84,8 +84,8 @@ $lang->doc->search = 'Search'; $lang->doc->allProduct = 'All' . $lang->productCommon; $lang->doc->allProject = 'All' . $lang->projectCommon; -$lang->doc->libTypeList['product'] = $lang->productCommon . ' Library'; -$lang->doc->libTypeList['project'] = $lang->projectCommon . ' Library'; +$lang->doc->libTypeList['product'] = $lang->productCommon . ' Scope'; +$lang->doc->libTypeList['project'] = $lang->projectCommon . ' Scope'; $lang->doc->libTypeList['custom'] = 'Custom Library'; $lang->doc->systemLibs['product'] = $lang->productCommon . 'Doc Lib'; @@ -127,14 +127,14 @@ $lang->doc->placeholder->url = 'Url'; $lang->doclib = new stdclass(); $lang->doclib->name = 'Name'; -$lang->doclib->control = 'Privilege'; +$lang->doclib->control = 'Access Control'; $lang->doclib->group = 'Group'; $lang->doclib->user = 'User'; $lang->doclib->files = 'Files'; -$lang->doclib->all = 'All'; +$lang->doclib->all = 'All Library'; $lang->doclib->select = 'Select'; $lang->doclib->project = $lang->projectCommon . ' Library'; $lang->doclib->product = $lang->productCommon . ' Library'; -$lang->doclib->main['product'] = $lang->productCommon . ' Main'; -$lang->doclib->main['project'] = $lang->projectCommon . ' Main'; +$lang->doclib->main['product'] = 'Main Lib'; +$lang->doclib->main['project'] = 'Main Lib'; diff --git a/module/doc/lang/zh-tw.php b/module/doc/lang/zh-tw.php index 47903d006e..9f18df2444 100644 --- a/module/doc/lang/zh-tw.php +++ b/module/doc/lang/zh-tw.php @@ -64,6 +64,7 @@ $lang->doc->manageType = '維護分類'; $lang->doc->editType = '編輯分類'; $lang->doc->deleteType = '刪除分類'; $lang->doc->addType = '增加分類'; +$lang->doc->childType = '子分類'; $lang->doc->libName = '文檔庫名稱'; $lang->doc->libType = '文檔庫類型'; diff --git a/module/doc/model.php b/module/doc/model.php index 9345c10628..574f7ec20a 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -15,10 +15,10 @@ class docModel extends model { /** * Set menus - * - * @param array $libs - * @param int $libID - * @param string $moduleID + * + * @param array $libs + * @param int $libID + * @param string $moduleID * @access public * @return void */ @@ -80,8 +80,8 @@ class docModel extends model /** * Get library by id. - * - * @param int $libID + * + * @param int $libID * @access public * @return object */ @@ -92,7 +92,7 @@ class docModel extends model /** * Get libraries. - * + * * @access public * @return array */ @@ -127,7 +127,7 @@ class docModel extends model /** * Create a library. - * + * * @access public * @return void */ @@ -151,8 +151,8 @@ class docModel extends model /** * Update a library. - * - * @param int $libID + * + * @param int $libID * @access public * @return void */ @@ -373,7 +373,7 @@ class docModel extends model /** * Create a doc. - * + * * @access public * @return void */ @@ -438,8 +438,8 @@ class docModel extends model /** * Update a doc. - * - * @param int $docID + * + * @param int $docID * @access public * @return void */ @@ -541,7 +541,7 @@ class docModel extends model /** * Get pairs of project modules. - * + * * @access public * @return array */ @@ -556,9 +556,9 @@ class docModel extends model /** * Get doc menu. - * - * @param int $libID - * @param int $parent + * + * @param int $libID + * @param int $parent * @access public * @return array */ @@ -576,8 +576,8 @@ class docModel extends model * Extract css styles for tables created in kindeditor. * * Like this:
    custom->user->fields['deleted'];?>custom->user->fields['deleted'];?> custom->deletedList, $showDeleted);?>
    "; + echo ""; if($id == 'actions') { echo $this->lang->actions; @@ -141,6 +142,7 @@ class datatableModel extends model } else { + if($id == 'id') echo "
    "; common::printOrderLink($id, $orderBy, $vars, $col->title); } echo '
    - * - * @param string $content + * + * @param string $content * @access public * @return void */ @@ -611,8 +611,8 @@ class docModel extends model /** * Check priv. - * - * @param object $object + * + * @param object $object * @access public * @return bool */ @@ -639,13 +639,13 @@ class docModel extends model if(strpos(",$object->groups,", ",$groupID,") !== false) return true; } } - + if(isset($object->lib)) { static $libs; if(empty($libs)) $libs = $this->getLibs('all'); if(!isset($libs[$object->lib])) return false; - + } if($object->project) @@ -667,10 +667,10 @@ class docModel extends model /** * Get all libs by type. - * - * @param string $type - * @param int $pager - * @param string $extra + * + * @param string $type + * @param int $pager + * @param string $extra * @access public * @return array */ @@ -708,7 +708,7 @@ class docModel extends model /** * Get all lib groups. - * + * * @access public * @return array */ @@ -792,9 +792,9 @@ class docModel extends model /** * Get limit libs. - * - * @param string $type - * @param int $limit + * + * @param string $type + * @param int $limit * @access public * @return array */ @@ -836,11 +836,11 @@ class docModel extends model } /** - * Get project or product libs groups. - * - * @param string $type - * @param array $idList - * @param int $limit + * Get project or product libs groups. + * + * @param string $type + * @param array $idList + * @param int $limit * @access public * @return array */ @@ -879,10 +879,10 @@ class docModel extends model /** * Get libs by object. - * - * @param string $type - * @param int $objectID - * @param string $mode + * + * @param string $type + * @param int $objectID + * @param string $mode * @access public * @return array */ @@ -983,8 +983,8 @@ class docModel extends model /** * Get doc tree. - * - * @param int $libID + * + * @param int $libID * @access public * @return array */ @@ -1003,9 +1003,9 @@ class docModel extends model /** * Fill docs in tree. - * - * @param object $node - * @param int $libID + * + * @param object $node + * @param int $libID * @access public * @return array */ @@ -1063,11 +1063,11 @@ class docModel extends model } /** - * Get crumbs. - * - * @param int $libID - * @param int $moduleID - * @param int $docID + * Get crumbs. + * + * @param int $libID + * @param int $moduleID + * @param int $docID * @access public * @return string */ @@ -1076,7 +1076,7 @@ class docModel extends model if(empty($libID)) return ''; $lib = $this->getLibById($libID); - if(!$this->checkPriv($lib)) + if(!$this->checkPriv($lib)) { echo(js::alert($this->lang->doc->accessDenied)); $loginLink = $this->config->requestType == 'GET' ? "?{$this->config->moduleVar}=user&{$this->config->methodVar}=login" : "user{$this->config->requestFix}login"; @@ -1116,9 +1116,9 @@ class docModel extends model /** * Get product crumb. - * - * @param int $productID - * @param int $projectID + * + * @param int $productID + * @param int $projectID * @access public * @return string */ @@ -1147,9 +1147,9 @@ class docModel extends model /** * Set lib users. - * - * @param string $type - * @param int $objectID + * + * @param string $type + * @param int $objectID * @access public * @return bool */ @@ -1159,15 +1159,16 @@ class docModel extends model if($type == 'product') { $teams = $this->dao->select('t1.account')->from(TABLE_TEAM)->alias('t1') - ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.project=t2.project') - ->leftJoin(TABLE_PROJECT)->alias('t3')->on('t1.project=t3.id') + ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.root=t2.project') + ->leftJoin(TABLE_PROJECT)->alias('t3')->on('t1.root=t3.id') ->where('t2.product')->eq($objectID) + ->andWhere('t1.type')->eq('project') ->andWhere('t3.deleted')->eq('0') ->fetchPairs('account', 'account'); } elseif($type == 'project') { - $teams = $this->dao->select('account')->from(TABLE_TEAM)->where('project')->eq($objectID)->fetchPairs('account', 'account'); + $teams = $this->dao->select('account')->from(TABLE_TEAM)->where('root')->eq($objectID)->andWhere('type')->eq('project')->fetchPairs('account', 'account'); } return $teams; diff --git a/module/doc/view/create.html.php b/module/doc/view/create.html.php index 69974b50ad..34ae349d3c 100644 --- a/module/doc/view/create.html.php +++ b/module/doc/view/create.html.php @@ -24,7 +24,7 @@
    - + - +
    doc->module;?>doc->module;?> diff --git a/module/doc/view/showfiles.html.php b/module/doc/view/showfiles.html.php index 0d190921c9..4892ad6917 100644 --- a/module/doc/view/showfiles.html.php +++ b/module/doc/view/showfiles.html.php @@ -72,7 +72,7 @@ pathname;?> extension;?> size / 1024 , 1) . 'K';?>addedBy) ? $file->addedBy : '';?>addedBy) ? zget($users, $file->addedBy) : '';?> addedDate) ? substr($file->addedDate, 0, 10) : '';?>
    -
    - doc->content;?> -
    - content; - if($doc->type == 'url') - { - $url = $doc->content; - if(!preg_match('/^https?:\/\//', $doc->content)) $url = 'http://' . $url; - $content = html::a($url, $doc->content, '_blank'); - } - echo $content; - ?> -
    - files as $file):?> - extension, $config->file->imageExtensions)):?> - file->uploadDate . substr($file->addedDate, 0, 10);?> -
  • - - id}");?>" alt="title?>"> - - - ", '', "class='btn-icon' onclick='deleteFile($file->id)' title='$lang->delete'");?> - -
  • - files[$file->id]);?> - - -
    - -
    fetch('file', 'printFiles', array('files' => $doc->files, 'fieldset' => 'false'));?>
    +
    + content; + if($doc->type == 'url') + { + $url = $doc->content; + if(!preg_match('/^https?:\/\//', $doc->content)) $url = 'http://' . $url; + $content = html::a($url, $doc->content, '_blank'); + } + echo $content; + ?> +
    + files as $file):?> + extension, $config->file->imageExtensions)):?> + file->uploadDate . substr($file->addedDate, 0, 10);?> +
  • + + id}");?>" alt="title?>"> + + + ", '', "class='btn-icon' onclick='deleteFile($file->id)' title='$lang->delete'");?> + +
  • + files[$file->id]);?> + +
    -
    + +
    fetch('file', 'printFiles', array('files' => $doc->files, 'fieldset' => 'false'));?>
    +
    deleted) echo $actionLinks;?>
    - +
    comment;?> id")?>' target='hiddenwin'> @@ -133,7 +130,7 @@
    -
    +
    +
    diff --git a/module/editor/lang/en.php b/module/editor/lang/en.php index a6bd08f16d..d8bb227313 100644 --- a/module/editor/lang/en.php +++ b/module/editor/lang/en.php @@ -69,7 +69,7 @@ $lang->editor->modules['story'] = 'Story'; $lang->editor->modules['task'] = 'Task'; $lang->editor->modules['testcase'] = 'Case'; $lang->editor->modules['testtask'] = 'Test Task'; -$lang->editor->modules['todo'] = 'To-Do'; +$lang->editor->modules['todo'] = 'Todo'; $lang->editor->modules['tree'] = 'Module'; $lang->editor->modules['upgrade'] = 'Upgrade'; $lang->editor->modules['user'] = 'User'; diff --git a/module/entry/config.php b/module/entry/config.php index 051b241f36..7f529f1375 100644 --- a/module/entry/config.php +++ b/module/entry/config.php @@ -6,3 +6,12 @@ $config->entry->edit = new stdclass(); $config->entry->edit->requiredFields = 'name, code, key'; $config->entry->help = 'http://www.zentao.net/book/zentaopmshelp/integration-287.html'; + +$config->entry->errcode['PARAM_CODE_MISSING'] = 401; +$config->entry->errcode['PARAM_TOKEN_MISSING'] = 401; +$config->entry->errcode['SESSION_CODE_MISSING'] = 401; +$config->entry->errcode['EMPTY_KEY'] = 401; +$config->entry->errcode['INVALID_TOKEN'] = 401; +$config->entry->errcode['SESSION_VERIFY_FAILED'] = 401; +$config->entry->errcode['IP_DENIED'] = 403; +$config->entry->errcode['EMPTY_ENTRY'] = 404; diff --git a/module/entry/lang/en.php b/module/entry/lang/en.php index f7ded928be..d99fbc11b7 100644 --- a/module/entry/lang/en.php +++ b/module/entry/lang/en.php @@ -34,3 +34,12 @@ $lang->entry->note->name = 'Name'; $lang->entry->note->code = 'Code, should be english and number.'; $lang->entry->note->ip = "Use comma between two IPs. IP segment is supported, e.g. 192.168.1.*"; $lang->entry->note->allIP = 'All'; + +$lang->entry->errmsg['PARAM_CODE_MISSING'] = 'Param code is missing.'; +$lang->entry->errmsg['PARAM_TOKEN_MISSING'] = 'Param token is missing.'; +$lang->entry->errmsg['SESSION_CODE_MISSING'] = 'Session code is missing.'; +$lang->entry->errmsg['EMPTY_KEY'] = 'Key of entry is missing.'; +$lang->entry->errmsg['INVALID_TOKEN'] = 'Invalid token.'; +$lang->entry->errmsg['SESSION_VERIFY_FAILED'] = 'Session verification failed.'; +$lang->entry->errmsg['IP_DENIED'] = 'IP is denied.'; +$lang->entry->errmsg['EMPTY_ENTRY'] = 'Key of entry is missing.'; diff --git a/module/entry/lang/zh-cn.php b/module/entry/lang/zh-cn.php index af5ce13432..c2afc09d0d 100644 --- a/module/entry/lang/zh-cn.php +++ b/module/entry/lang/zh-cn.php @@ -34,3 +34,12 @@ $lang->entry->note->name = '授权应用名称'; $lang->entry->note->code = '授权应用代号,必须为字母或数字的组合'; $lang->entry->note->ip = "允许访问API的应用ip,多个ip用逗号隔开。支持IP段,如192.168.1.*"; $lang->entry->note->allIP = '无限制'; + +$lang->entry->errmsg['PARAM_CODE_MISSING'] = '缺少code参数'; +$lang->entry->errmsg['PARAM_TOKEN_MISSING'] = '缺少token参数'; +$lang->entry->errmsg['SESSION_CODE_MISSING'] = '缺少session code'; +$lang->entry->errmsg['EMPTY_KEY'] = '应用未设置密钥'; +$lang->entry->errmsg['INVALID_TOKEN'] = '无效的token参数'; +$lang->entry->errmsg['SESSION_VERIFY_FAILED'] = 'session验证失败'; +$lang->entry->errmsg['IP_DENIED'] = '该IP被限制访问'; +$lang->entry->errmsg['EMPTY_ENTRY'] = '应用不存在'; diff --git a/module/extension/lang/zh-tw.php b/module/extension/lang/zh-tw.php index d4a863996c..661f560f6f 100644 --- a/module/extension/lang/zh-tw.php +++ b/module/extension/lang/zh-tw.php @@ -46,6 +46,7 @@ $lang->extension->downloads = '下載量'; $lang->extension->compatible = '兼容性'; $lang->extension->grade = '評分'; $lang->extension->depends = '依賴'; +$lang->extension->expireDate = '到期日期'; $lang->extension->zentaoCompatible = '適用版本'; $lang->extension->installedTime = '安裝時間'; diff --git a/module/file/control.php b/module/file/control.php index 6ba97d5fd7..3dbdaf656b 100644 --- a/module/file/control.php +++ b/module/file/control.php @@ -13,9 +13,9 @@ class file extends control { /** * Build the upload form. - * - * @param int $fileCount - * @param float $percent + * + * @param int $fileCount + * @param float $percent * @param string $filesName * @param string $labelsName * @access public @@ -23,7 +23,7 @@ class file extends control */ public function buildForm($fileCount = 1, $percent = 0.9, $filesName = 'files', $labelsName = 'labels') { - if(!file_exists($this->file->savePath)) + if(!file_exists($this->file->savePath)) { printf($this->lang->file->errorNotExists, $this->file->savePath); return false; @@ -43,7 +43,7 @@ class file extends control /** * AJAX: get upload request from the web editor. - * + * * @access public * @return void */ @@ -79,7 +79,7 @@ class file extends control /** * AJAX: get upload request from the web editor. - * + * * @access public * @return void */ @@ -120,9 +120,9 @@ class file extends control /** * Down a file. - * - * @param int $fileID - * @param string $mouse + * + * @param int $fileID + * @param string $mouse * @access public * @return void */ @@ -142,7 +142,7 @@ class file extends control /* Judge the mode, down or open. */ $mode = 'down'; $fileTypes = 'txt|jpg|jpeg|gif|png|bmp|xml|html'; - if(stripos($fileTypes, $file->extension) !== false and $mouse == 'left') $mode = 'open'; + if(stripos($fileTypes, $file->extension) !== false && $mouse == 'left') $mode = 'open'; if(file_exists($file->realPath)) { @@ -177,7 +177,7 @@ class file extends control /** * Export as csv format. - * + * * @access public * @return void */ @@ -193,28 +193,28 @@ class file extends control /** * export as xml format - * + * * @access public * @return void */ - public function export2XML() - { + public function export2XML() + { $this->view->fields = $this->post->fields; $this->view->rows = $this->post->rows; - + $output = $this->parse('file', 'export2XML'); $this->sendDownHeader($this->post->fileName, 'xml', $output); - } + } /** * export as html format - * + * * @access public * @return void */ - public function export2HTML() - { + public function export2HTML() + { $this->view->fields = $this->post->fields; $this->view->rows = $this->post->rows; $this->host = common::getSysURL(); @@ -224,25 +224,25 @@ class file extends control case 'task': foreach($this->view->rows as $row) { - $row->name = html::a($this->host . $this->createLink('task', 'view', "taskID=$row->id"), $row->name); + $row->name = html::a($this->host . $this->createLink('task', 'view', "taskID=$row->id"), $row->name); } break; case 'story': foreach($this->view->rows as $row) { - $row->title= html::a($this->host . $this->createLink('story', 'view', "storyID=$row->id"), $row->title); + $row->title= html::a($this->host . $this->createLink('story', 'view', "storyID=$row->id"), $row->title); } break; case 'bug': foreach($this->view->rows as $row) { - $row->title= html::a($this->host . $this->createLink('bug', 'view', "bugID=$row->id"), $row->title); + $row->title= html::a($this->host . $this->createLink('bug', 'view', "bugID=$row->id"), $row->title); } break; case 'testcase': foreach($this->view->rows as $row) { - $row->title= html::a($this->host . $this->createLink('testcase', 'view', "caseID=$row->id"), $row->title); + $row->title= html::a($this->host . $this->createLink('testcase', 'view', "caseID=$row->id"), $row->title); } break; } @@ -250,13 +250,13 @@ class file extends control $output = $this->parse('file', 'export2Html'); $this->sendDownHeader($this->post->fileName, 'html', $output); - } + } /** * Send the download header to the client. - * - * @param string $fileName - * @param string $extension + * + * @param string $fileName + * @param string $extension * @access public * @return void */ @@ -289,8 +289,8 @@ class file extends control /** * Delete a file. - * - * @param int $fileID + * + * @param int $fileID * @param string $confirm yes|no * @access public * @return void @@ -312,10 +312,10 @@ class file extends control } /** - * Print files. - * - * @param array $files - * @param string $fieldset + * Print files. + * + * @param array $files + * @param string $fieldset * @access public * @return void */ @@ -327,9 +327,9 @@ class file extends control } /** - * Edit file's name. - * - * @param int $fileID + * Edit file's name. + * + * @param int $fileID * @access public * @return void */ @@ -355,8 +355,8 @@ class file extends control } /** - * Paste image in kindeditor at firefox and chrome. - * + * Paste image in kindeditor at firefox and chrome. + * * @access public * @return void */ @@ -370,9 +370,9 @@ class file extends control /** * Upload Images. - * - * @param string $module - * @param string $params + * + * @param string $module + * @param string $params * @access public * @return void */ @@ -424,9 +424,9 @@ class file extends control /** * Build export tpl. - * - * @param string $module - * @param int $templateID + * + * @param string $module + * @param int $templateID * @access public * @return void */ @@ -444,8 +444,8 @@ class file extends control /** * Ajax save template. - * - * @param string $module + * + * @param string $module * @access public * @return void */ @@ -462,8 +462,8 @@ class file extends control /** * Ajax delete template. - * - * @param int $templateID + * + * @param int $templateID * @access public * @return void */ @@ -474,9 +474,9 @@ class file extends control } /** - * Read file. - * - * @param int $fileID + * Read file. + * + * @param int $fileID * @access public * @return void */ diff --git a/module/file/lang/en.php b/module/file/lang/en.php index 48ee394ecc..9e5a8fa7ea 100644 --- a/module/file/lang/en.php +++ b/module/file/lang/en.php @@ -10,7 +10,7 @@ * @link http://www.zentao.net */ $lang->file = new stdclass(); -$lang->file->common = 'Attachment'; +$lang->file->common = 'File'; $lang->file->uploadImages = 'Batch Upload Images'; $lang->file->download = 'Download Files'; $lang->file->uploadDate = 'Uploaded on'; @@ -26,16 +26,16 @@ $lang->file->exportFields = "Fileds to be Exported"; $lang->file->defaultTPL = "Default Template"; $lang->file->setExportTPL = "Settings"; $lang->file->preview = "Preview"; -$lang->file->addFile = 'Add File'; -$lang->file->beginUpload = 'Start uploading'; -$lang->file->uploadSuccess = 'uploaded Successfully'; +$lang->file->addFile = 'Add'; +$lang->file->beginUpload = 'Upload'; +$lang->file->uploadSuccess = 'Uploaded!'; $lang->file->pathname = 'Path Name'; $lang->file->title = 'Title'; $lang->file->extension = 'Extension'; $lang->file->size = 'Size'; $lang->file->addedBy = 'Added By'; -$lang->file->addedDate = 'Added Date'; +$lang->file->addedDate = 'Added On'; $lang->file->downloads = 'Downloads'; $lang->file->extra = 'Extra'; @@ -50,4 +50,4 @@ $lang->file->errorFileMove = " Uploading failed, there was an error when movi $lang->file->dangerFile = " File has been rejected to upload for security issues."; $lang->file->errorSuffix = 'Format is incorrect. .zip files ONLY!'; $lang->file->errorExtract = 'Extracting file failed. File might be damaged or invalid files in the zip package.'; -$lang->file->uploadImagesExplain = 'Note: please upload "jpg, jpeg, gif, png" format of the picture, the program will use the file name as the title, the picture as content.'; +$lang->file->uploadImagesExplain = 'Note: upload .jpg, .jpeg, .gif, and .png images. The image name will be taken as the title of the story and the image as its content.'; diff --git a/module/file/view/download.html.php b/module/file/view/download.html.php index 551102445e..6a7f742e8c 100644 --- a/module/file/view/download.html.php +++ b/module/file/view/download.html.php @@ -29,9 +29,9 @@ } else { - if(!extension_loaded('mbstring')) + if(extension_loaded('mbstring')) { - $encoding = mb_detect_encoding($fileContent, array('ASCII','UTF-8','GB2312','GBK','BIG5')); + $encoding = mb_detect_encoding($fileContent, array('ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5')); if($encoding != 'UTF-8') $fileContent = helper::convertEncoding($fileContent, $encoding, $config->charset); } else diff --git a/module/file/view/export.html.php b/module/file/view/export.html.php index 904b1916d8..d37e25bbf2 100644 --- a/module/file/view/export.html.php +++ b/module/file/view/export.html.php @@ -167,7 +167,6 @@ $(document).ready(function() if(!$hasDefaultField)$selectedFields[] = $field; } ?> -
    +
    + diff --git a/module/my/view/todo.html.php b/module/my/view/todo.html.php index 96cd9268b8..cc85fd9bf8 100644 --- a/module/my/view/todo.html.php +++ b/module/my/view/todo.html.php @@ -13,95 +13,100 @@ todo->confirmDelete)?> -
    - -
    - " . $lang->todo->export, '', "class='btn export'") ?> - " . $lang->todo->batchCreate, '', "class='btn'") ?> - " . $lang->todo->create, '', "class='btn'") ?> -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    idAB);?> todo->date);?> todo->type);?> priAB);?> todo->name);?> todo->beginAB);?> todo->endAB);?>todo->status);?>actions;?>
    - - - - id; ?> - date == '2030-01-01' ? $lang->todo->periods['future'] : $todo->date;?>todo->typeList[$todo->type];?>todo->priList, $todo->pri, $todo->pri);?>'>todo->priList, $todo->pri, $todo->pri)?>createLink('todo', 'view', "id=$todo->id&from=my", '', true), $todo->name, '', "data-toggle='modal' data-type='iframe' data-title='" . $lang->todo->view . "' data-icon='check'");?>begin;?>end;?>todo->statusList[$todo->status];?> - id", $todo, 'list', 'ok-sign', 'hiddenwin'); - common::printIcon('todo', 'edit', "id=$todo->id", '', 'list', 'pencil', '', 'iframe', true); - - if(common::hasPriv('todo', 'delete')) - { - $deleteURL = $this->createLink('todo', 'delete', "todoID=$todo->id&confirm=yes"); - echo html::a("javascript:ajaxDelete(\"$deleteURL\",\"todoList\",confirmDelete)", '', '', "class='btn-icon' title='{$lang->todo->delete}'"); - } + $label = $period == 'all' ? "$label {$todoCount}" : "$label"; + $active = $period == $type ? 'btn-active-text' : ''; + echo html::a(inlink('todo', $vars), $label, '', "class='btn btn-link $active' id='{$period}'") ?> -
    -
    - "; + +
    + + +
    +
    +
    + " . $lang->todo->export, '', "class='btn btn-link iframe'");?> + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    + + idAB);?> +
    todo->date);?> todo->type);?> priAB);?> todo->name);?> todo->beginAB);?> todo->endAB);?>todo->status);?>actions;?>
    +
    + + + + + id?> +
    +
    date == '2030-01-01' ? $lang->todo->periods['future'] : $todo->date;?>todo->typeList[$todo->type];?> pri;?>'>todo->priList, $todo->pri, $todo->pri)?>createLink('todo', 'view', "id=$todo->id&from=my", '', true), $todo->name, '', "data-toggle='modal' data-type='iframe' data-title='" . $lang->todo->view . "' data-icon='check'");?>begin;?>end;?>todo->statusList[$todo->status];?> + status != 'done') common::printIcon('todo', 'assignto', "todoID=$todo->id", $todo, 'list', 'hand-right', '', "btn-icon", '', "data-toggle='assigntoModal'", $lang->todo->assignTo); + if($todo->status == 'done') common::printIcon('todo', 'activate', "id=$todo->id", $todo, 'list', 'magic', 'hiddenwin'); + if($todo->status != 'done') common::printIcon('todo', 'finish', "id=$todo->id", $todo, 'list', 'checked', 'hiddenwin'); + if($todo->status == 'done') common::printIcon('todo', 'close', "id=$todo->id", $todo, 'list', 'off', 'hiddenwin'); + common::printIcon('todo', 'edit', "id=$todo->id", '', 'list', 'edit', '', 'iframe', true); + + if(common::hasPriv('todo', 'delete')) + { + $deleteURL = $this->createLink('todo', 'delete', "todoID=$todo->id&confirm=yes"); + echo html::a("javascript:ajaxDelete(\"$deleteURL\",\"todoList\",confirmDelete)", '', '', "class='btn' title='{$lang->todo->delete}'"); + } + ?> +
    + +
    -
    + + show('right', 'pagerjs');?> +
    + + +
    + + + diff --git a/module/product/lang/en.php b/module/product/lang/en.php index b80d3e5ee3..77e950a488 100644 --- a/module/product/lang/en.php +++ b/module/product/lang/en.php @@ -9,11 +9,11 @@ * @version $Id: en.php 5091 2013-07-10 06:06:46Z chencongzhi520@gmail.com $ * @link http://www.zentao.net */ -$lang->product->common = $lang->productCommon . 'View'; +$lang->product->common = $lang->productCommon; $lang->product->index = $lang->productCommon . "Home"; $lang->product->browse = "Story List"; $lang->product->dynamic = "Dynamic"; -$lang->product->view = "{$lang->productCommon}s"; +$lang->product->view = "Overview"; $lang->product->edit = "Edit {$lang->productCommon}"; $lang->product->batchEdit = "Batch Edit"; $lang->product->create = "Create {$lang->productCommon}"; @@ -31,24 +31,25 @@ $lang->product->export = "Export"; $lang->product->basicInfo = 'Basic Info'; $lang->product->otherInfo = 'Other Info'; -$lang->product->plans = 'Plans'; -$lang->product->releases = 'Releases'; +$lang->product->plans = 'Plan'; +$lang->product->releases = 'Release'; $lang->product->docs = 'Doc'; $lang->product->bugs = 'Linked Bug'; $lang->product->projects = "Linked {$lang->projectCommon}"; -$lang->product->cases = 'Cases'; -$lang->product->builds = 'Builds'; +$lang->product->cases = 'Case'; +$lang->product->builds = 'Build'; $lang->product->roadmap = 'Roadmap'; $lang->product->doc = 'Doc'; $lang->product->project = $lang->projectCommon . 'List'; $lang->product->build = 'Build'; +$lang->product->currentProject = 'Current Project'; $lang->product->activeStories = 'Activated Story'; $lang->product->changedStories = 'Changed Story'; $lang->product->draftStories = 'Draft Story'; $lang->product->closedStories = 'Closed Story'; $lang->product->unResolvedBugs = 'Unresolved Bug'; -$lang->product->assignToNullBugs = 'No Assigned Bug'; +$lang->product->assignToNullBugs = 'Unassigned Bug'; $lang->product->confirmDelete = " Do you want to delete {$lang->productCommon}?"; @@ -64,27 +65,27 @@ $lang->product->type = "Type"; $lang->product->status = 'Status'; $lang->product->desc = 'Description'; $lang->product->PO = "PO"; -$lang->product->QD = 'QD'; -$lang->product->RD = 'RD'; -$lang->product->acl = 'Acceptance'; +$lang->product->QD = 'QA Manager'; +$lang->product->RD = 'Release Manager'; +$lang->product->acl = 'Access Control'; $lang->product->whitelist = 'Whitelist'; $lang->product->branch = '%s'; $lang->product->searchStory = 'Search'; -$lang->product->assignedToMe = 'Assigned to Me'; -$lang->product->openedByMe = 'Created by Me'; -$lang->product->reviewedByMe = 'Reviewed by Me'; -$lang->product->closedByMe = 'Closed by Me'; +$lang->product->assignedToMe = 'Assigned To Me'; +$lang->product->openedByMe = 'Created By Me'; +$lang->product->reviewedByMe = 'Reviewed By Me'; +$lang->product->closedByMe = 'ClosedByMe'; $lang->product->draftStory = 'Draft'; -$lang->product->activeStory = 'Activate'; +$lang->product->activeStory = 'Activated'; $lang->product->changedStory = 'Changed'; -$lang->product->willClose = 'To be Closed'; +$lang->product->willClose = 'ToBeClose'; $lang->product->closedStory = 'Closed'; $lang->product->unclosed = 'Open'; -$lang->product->unplan = 'No plan'; +$lang->product->unplan = 'Wait'; $lang->product->my = 'My'; -$lang->product->allStory = 'All Stories'; +$lang->product->allStory = 'All'; $lang->product->allProduct = 'All' . $lang->productCommon; $lang->product->allProductsOfProject = 'All linked' . $lang->productCommon; @@ -120,6 +121,9 @@ $lang->product->mySelects['resolvedbyme'] = $lang->product->reviewedByMe; $lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed; $lang->product->featureBar['browse']['unplan'] = $lang->product->unplan; $lang->product->featureBar['browse']['allstory'] = $lang->product->allStory; + + + $lang->product->featureBar['browse']['my'] = $lang->product->my; $lang->product->featureBar['browse']['closedbyme'] = $lang->product->closedByMe; $lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory; diff --git a/module/product/lang/zh-cn.php b/module/product/lang/zh-cn.php index e5fadf1a90..086cea20db 100644 --- a/module/product/lang/zh-cn.php +++ b/module/product/lang/zh-cn.php @@ -43,6 +43,7 @@ $lang->product->doc = '文档列表'; $lang->product->project = $lang->projectCommon . '列表'; $lang->product->build = '版本列表'; +$lang->product->currentProject = '当前项目'; $lang->product->activeStories = '激活需求'; $lang->product->changedStories = '已变更需求'; $lang->product->draftStories = '草稿需求'; @@ -83,6 +84,7 @@ $lang->product->closedStory = '已关闭'; $lang->product->unclosed = '未关闭'; $lang->product->unplan = '未计划'; + $lang->product->allStory = '全部需求'; $lang->product->allProduct = '全部' . $lang->productCommon; $lang->product->allProductsOfProject = '全部关联' . $lang->productCommon; @@ -112,12 +114,17 @@ $lang->product->storySummary = "本页共 %s 个需求,预 $lang->product->checkedSummary = "选中 %total% 个需求,预计 %estimate% 个工时,用例覆盖率%rate%。"; $lang->product->noMatched = '找不到包含"%s"的' . $lang->productCommon; + + + + $lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed; $lang->product->featureBar['browse']['unplan'] = $lang->product->unplan; $lang->product->featureBar['browse']['allstory'] = $lang->product->allStory; $lang->product->featureBar['browse']['assignedtome'] = $lang->product->assignedToMe; $lang->product->featureBar['browse']['openedbyme'] = $lang->product->openedByMe; $lang->product->featureBar['browse']['reviewedbyme'] = $lang->product->reviewedByMe; + $lang->product->featureBar['browse']['closedbyme'] = $lang->product->closedByMe; $lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory; $lang->product->featureBar['browse']['activestory'] = $lang->product->activeStory; diff --git a/module/product/lang/zh-tw.php b/module/product/lang/zh-tw.php index 6e59b146bc..72c90a08b6 100644 --- a/module/product/lang/zh-tw.php +++ b/module/product/lang/zh-tw.php @@ -16,7 +16,7 @@ $lang->product->dynamic = "動態"; $lang->product->view = "{$lang->productCommon}概況"; $lang->product->edit = "編輯{$lang->productCommon}"; $lang->product->batchEdit = "批量編輯"; -$lang->product->create = "新增{$lang->productCommon}"; +$lang->product->create = "添加{$lang->productCommon}"; $lang->product->delete = "刪除{$lang->productCommon}"; $lang->product->deleted = "已刪除"; $lang->product->close = "關閉"; @@ -43,6 +43,7 @@ $lang->product->doc = '文檔列表'; $lang->product->project = $lang->projectCommon . '列表'; $lang->product->build = '版本列表'; +$lang->product->currentProject = '當前項目'; $lang->product->activeStories = '激活需求'; $lang->product->changedStories = '已變更需求'; $lang->product->draftStories = '草稿需求'; @@ -71,16 +72,18 @@ $lang->product->whitelist = '分組白名單'; $lang->product->branch = '所屬%s'; $lang->product->searchStory = '搜索'; -$lang->product->assignedToMe = '指派給我'; -$lang->product->openedByMe = '由我創建'; -$lang->product->reviewedByMe = '由我評審'; -$lang->product->closedByMe = '由我關閉'; +$lang->product->assignedToMe = '指給我'; +$lang->product->openedByMe = '我創建'; +$lang->product->reviewedByMe = '我評審'; +$lang->product->closedByMe = '我關閉'; $lang->product->draftStory = '草稿'; $lang->product->activeStory = '激活'; $lang->product->changedStory = '已變更'; $lang->product->willClose = '待關閉'; $lang->product->closedStory = '已關閉'; $lang->product->unclosed = '未關閉'; +$lang->product->unplan = '未計劃'; + $lang->product->allStory = '全部需求'; $lang->product->allProduct = '全部' . $lang->productCommon; @@ -107,14 +110,21 @@ $lang->product->aclList['open'] = "預設設置(有{$lang->productCommon}視 $lang->product->aclList['private'] = "私有{$lang->productCommon}(只有{$lang->productCommon}相關負責人和{$lang->projectCommon}團隊成員才能訪問)"; $lang->product->aclList['custom'] = '自定義白名單(團隊成員和白名單的成員可以訪問)'; -$lang->product->storySummary = "本頁共 %s 個需求,預計 %s 個工時,用例覆蓋率%s。"; -$lang->product->noMatched = '找不到包含"%s"的' . $lang->productCommon; +$lang->product->storySummary = "本頁共 %s 個需求,預計 %s 個工時,用例覆蓋率%s。"; +$lang->product->checkedSummary = "選中 %total% 個需求,預計 %estimate% 個工時,用例覆蓋率%rate%。"; +$lang->product->noMatched = '找不到包含"%s"的' . $lang->productCommon; + + + + $lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed; +$lang->product->featureBar['browse']['unplan'] = $lang->product->unplan; $lang->product->featureBar['browse']['allstory'] = $lang->product->allStory; $lang->product->featureBar['browse']['assignedtome'] = $lang->product->assignedToMe; $lang->product->featureBar['browse']['openedbyme'] = $lang->product->openedByMe; $lang->product->featureBar['browse']['reviewedbyme'] = $lang->product->reviewedByMe; + $lang->product->featureBar['browse']['closedbyme'] = $lang->product->closedByMe; $lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory; $lang->product->featureBar['browse']['activestory'] = $lang->product->activeStory; diff --git a/module/product/model.php b/module/product/model.php index 9f9a0f8f3f..88eddf0328 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -614,10 +614,11 @@ class productModel extends model } if(empty($teams)) { - $teams = $this->dao->select('t1.project, t1.account')->from(TABLE_TEAM)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + $teams = $this->dao->select('t1.root, t1.account')->from(TABLE_TEAM)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.root = t2.id') ->where('t2.deleted')->eq(0) - ->fetchGroup('project', 'account'); + ->andWhere('t1.type')->eq('project') + ->fetchGroup('root', 'account'); } if(!isset($projects[$product->id])) return $members; @@ -773,36 +774,71 @@ class productModel extends model return $stats; } + /** + * Get priv products. + * + * @access public + * @return array + */ public function getPrivProducts() { $account = ',' . $this->app->user->account . ','; static $products; if($products === null) { - $groupSql = ''; + $groups = ''; if(isset($this->app->user->groups)) { - foreach($this->app->user->groups as $group) $groupSql .= "INSTR(CONCAT(',', t1.whitelist, ','), ',$group,') > 0 OR "; + foreach($this->app->user->groups as $group) $groups .= ",$group,"; } - $groupSql = !empty($groupSql) ? '(' . substr($groupSql, 0, strlen($groupSql) - 4) . ')' : '1 != 1'; - $products = $this->dao->select('distinct t1.id')->from(TABLE_PRODUCT)->alias('t1') + $stmt = $this->dao->select('distinct t1.*,t3.type as teamType,t3.account as teamAccount,t4.deleted as projectDeleted')->from(TABLE_PRODUCT)->alias('t1') ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.product') - ->leftJoin(TABLE_TEAM)->alias('t3')->on('t2.project = t3.project') + ->leftJoin(TABLE_TEAM)->alias('t3')->on('t2.project = t3.root') ->leftJoin(TABLE_PROJECT)->alias('t4')->on('t2.project = t4.id') - ->beginIF($this->app->user->admin)->where('t1.deleted')->eq(0)->fi() - ->beginIF(!$this->app->user->admin) - ->where('t1.acl')->eq('open') - ->orWhere("(t1.acl = 'custom' AND $groupSql)") - ->orWhere('t1.PO')->eq($this->app->user->account) - ->orWhere('t1.QD')->eq($this->app->user->account) - ->orWhere('t1.RD')->eq($this->app->user->account) - ->orWhere('t1.createdBy')->eq($this->app->user->account) - ->orWhere('t3.account')->eq($this->app->user->account) - ->andWhere('t1.deleted')->eq(0) - ->andWhere('t4.deleted')->eq(0) - ->fi() - ->fetchAll('id'); + ->where('t1.deleted')->eq(0) + ->query(); + + $products = array(); + $account = $this->app->user->account; + while($product = $stmt->fetch()) + { + $id = $product->id; + if($this->app->user->admin) + { + $products[$id] = $id; + } + else + { + if($product->PO == $account OR $product->QD == $account OR $product->RD == $account OR $product->createdBy == $account) + { + $products[$id] = $id; + continue; + } + if($product->teamType == 'project' and $product->teamAccount == $account and $product->projectDeleted == '0') + { + $products[$id] = $id; + continue; + } + if($product->acl == 'open') + { + $products[$id] = $id; + continue; + } + if($product->acl == 'custom') + { + foreach(explode(',', $product->whitelist) as $whitelist) + { + if(empty($whitelist)) continue; + if(strpos($groups, ",$whitelist,") !== false) + { + $products[$id] = $id; + break; + } + } + } + } + } } return $products; } diff --git a/module/product/view/all.html.php b/module/product/view/all.html.php index 6322c4bdb0..4c96ad190a 100644 --- a/module/product/view/all.html.php +++ b/module/product/view/all.html.php @@ -66,7 +66,7 @@ product->line);?> product->activeStories;?> product->changedStories;?> - product->draftStories;?> + product->draftStories;?> product->closedStories;?> product->plans;?> product->releases;?> diff --git a/module/product/view/build.html.php b/module/product/view/build.html.php index a07931ddf0..3ab95d193b 100755 --- a/module/product/view/build.html.php +++ b/module/product/view/build.html.php @@ -35,8 +35,8 @@ id;?> createLink('build', 'view', "build=$build->id"), $build->name);?> - scmPath, 'http') === true ? html::a($build->scmPath) : $build->scmPath;?> - filePath, 'http') === true ? html::a($build->filePath) : $build->filePath;?> + scmPath, 'http') === 0 ? html::a($build->scmPath) : $build->scmPath;?> + filePath, 'http') === 0 ? html::a($build->filePath) : $build->filePath;?> date?> builder]?> diff --git a/module/product/view/create.html.php b/module/product/view/create.html.php index f905b5854b..687bf6ac15 100644 --- a/module/product/view/create.html.php +++ b/module/product/view/create.html.php @@ -23,7 +23,7 @@
    - + diff --git a/module/product/view/dynamic.html.php b/module/product/view/dynamic.html.php index c18dd79ca1..18899fccea 100755 --- a/module/product/view/dynamic.html.php +++ b/module/product/view/dynamic.html.php @@ -31,10 +31,10 @@ recTotal}&recPerPage={$pager->recPerPage}"; ?> - + - + diff --git a/module/productplan/config.php b/module/productplan/config.php index c506aacdc0..0f7486b95b 100644 --- a/module/productplan/config.php +++ b/module/productplan/config.php @@ -2,8 +2,8 @@ $config->productplan = new stdclass(); $config->productplan->create = new stdclass(); $config->productplan->edit = new stdclass(); -$config->productplan->create->requiredFields = 'title,begin,end'; -$config->productplan->edit->requiredFields = 'title,begin,end'; +$config->productplan->create->requiredFields = 'title,begin'; +$config->productplan->edit->requiredFields = 'title,begin'; $config->productplan->editor = new stdclass(); $config->productplan->editor->create = array('id' => 'desc', 'tools' => 'simpleTools'); diff --git a/module/productplan/control.php b/module/productplan/control.php index 2a820a8806..261cfb3971 100644 --- a/module/productplan/control.php +++ b/module/productplan/control.php @@ -191,6 +191,7 @@ class productplan extends control */ public function browse($productID = 0, $branch = 0, $browseType = 'all', $orderBy = 'begin_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1 ) { + $this->app->loadLang('project'); /* Load pager. */ $this->app->loadClass('pager', $static = true); $pager = new pager($recTotal, $recPerPage, $pageID); diff --git a/module/productplan/js/create.js b/module/productplan/js/create.js index e58173c215..c7d495d46f 100644 --- a/module/productplan/js/create.js +++ b/module/productplan/js/create.js @@ -1,7 +1,7 @@ /** * Convert a date string like 2011-11-11 to date object in js. - * - * @param string $date + * + * @param string $date * @access public * @return date */ @@ -9,14 +9,14 @@ function convertStringToDate(dateString) { dateString = dateString.split('-'); dateString = dateString[1] + '/' + dateString[2] + '/' + dateString[0]; - + return Date.parse(dateString); } /** * Compute the end date for productplan. - * - * @param int $delta + * + * @param int $delta * @access public * @return void */ @@ -33,7 +33,15 @@ function computeEndDate(delta) } endDate = beginDate.addDays(delta - 1).toString('yyyy-MM-dd'); - $('#end').val(endDate); + + if(delta == 9999) + { + $('#end').val('').attr("disabled","disabled"); + } + else + { + $('#end').val(endDate).removeAttr('disabled'); + } } $('#begin').on('change', function() diff --git a/module/productplan/js/edit.js b/module/productplan/js/edit.js index b23058c54e..c7fb9892ad 100644 --- a/module/productplan/js/edit.js +++ b/module/productplan/js/edit.js @@ -1,7 +1,7 @@ /** * Convert a date string like 2011-11-11 to date object in js. - * - * @param string $date + * + * @param string $date * @access public * @return date */ @@ -9,14 +9,14 @@ function convertStringToDate(dateString) { dateString = dateString.split('-'); dateString = dateString[1] + '/' + dateString[2] + '/' + dateString[0]; - + return Date.parse(dateString); } /** * Compute the end date for productplan. - * - * @param int $delta + * + * @param int $delta * @access public * @return void */ @@ -33,5 +33,12 @@ function computeEndDate(delta) } endDate = beginDate.addDays(delta - 1).toString('yyyy-MM-dd'); - $('#end').val(endDate).datetimepicker('update') + if(delta == 9999) + { + $('#end').val('').attr("disabled","disabled"); + } + else + { + $('#end').val(endDate).removeAttr('disabled').datetimepicker('update'); + } } diff --git a/module/productplan/js/view.js b/module/productplan/js/view.js index 5222235cbc..ad52ab8eca 100644 --- a/module/productplan/js/view.js +++ b/module/productplan/js/view.js @@ -46,7 +46,6 @@ $(function() { var list = ''; for(i = 0; i < data.list.length; i++) list += $(data.list[i]).attr('data-id') + ','; - console.log(list); $.post(createLink('productplan', 'ajaxStorySort', 'planID=' + planID), {'storys' : list, 'orderBy' : orderBy}, function() { var $target = $(data.element[0]); diff --git a/module/productplan/lang/en.php b/module/productplan/lang/en.php index f0450c5f84..1db1ccba00 100644 --- a/module/productplan/lang/en.php +++ b/module/productplan/lang/en.php @@ -9,7 +9,7 @@ * @version $Id: en.php 4659 2013-04-17 06:45:08Z chencongzhi520@gmail.com $ * @link http://www.zentao.net */ -$lang->productplan->common = $lang->productCommon . 'Plan'; +$lang->productplan->common = $lang->productCommon . ' Plan'; $lang->productplan->browse = "View"; $lang->productplan->index = "List"; $lang->productplan->create = "Create"; @@ -17,20 +17,20 @@ $lang->productplan->edit = "Edit"; $lang->productplan->delete = "Delete"; $lang->productplan->view = "Details"; $lang->productplan->bugSummary = "%s Bugs in total on this page."; -$lang->productplan->info = 'Info'; +$lang->productplan->info = 'Info'; $lang->productplan->batchEdit = 'Batch Edit'; $lang->productplan->batchUnlink = "Batch Unlink"; -$lang->productplan->linkStory = "Linked Story"; +$lang->productplan->linkStory = "Link Story"; $lang->productplan->unlinkStory = "Unlink Story"; $lang->productplan->batchUnlinkStory = "Batch Unlink"; -$lang->productplan->linkedStories = 'link Story'; -$lang->productplan->unlinkedStories = 'UnLinkEd'; -$lang->productplan->updateOrder = 'Ranking'; +$lang->productplan->linkedStories = 'Linked Story'; +$lang->productplan->unlinkedStories = 'Unlinked Story'; +$lang->productplan->updateOrder = 'Sort'; $lang->productplan->linkBug = "Link Bug"; $lang->productplan->unlinkBug = "Unlink Bug"; -$lang->productplan->batchUnlinkBug = "Batch Unlink"; +$lang->productplan->batchUnlinkBug = "Batch Unlink Bug"; $lang->productplan->linkedBugs = 'Linked Bug'; $lang->productplan->unlinkedBugs = 'Unlinked'; @@ -46,14 +46,20 @@ $lang->productplan->desc = 'Description'; $lang->productplan->begin = 'Begin'; $lang->productplan->end = 'End'; $lang->productplan->last = 'Last plan'; +$lang->productplan->future = 'Future'; +$lang->productplan->stories = 'Stories'; +$lang->productplan->bugs = 'Bugs'; +$lang->productplan->hour = 'Hour'; +$lang->productplan->project = $lang->projectCommon; -$lang->productplan->endList[7] = '1 Week'; -$lang->productplan->endList[14] = '2 Weeks'; -$lang->productplan->endList[31] = '1 Month'; -$lang->productplan->endList[62] = '2 Months'; -$lang->productplan->endList[93] = '3 Months'; -$lang->productplan->endList[186] = '6 Months'; -$lang->productplan->endList[365] = '1 Year'; +$lang->productplan->endList[7] = '1 Week'; +$lang->productplan->endList[14] = '2 Weeks'; +$lang->productplan->endList[31] = '1 Month'; +$lang->productplan->endList[62] = '2 Months'; +$lang->productplan->endList[93] = '3 Months'; +$lang->productplan->endList[186] = '6 Months'; +$lang->productplan->endList[365] = '1 Year'; +$lang->productplan->endList[9999] = 'Future'; $lang->productplan->errorNoTitle = 'ID %s title should not be empty.'; $lang->productplan->errorNoBegin = 'ID %s begin time should not be empty.'; @@ -61,5 +67,5 @@ $lang->productplan->errorNoEnd = 'ID %s end time should not be empty.'; $lang->productplan->beginGeEnd = 'ID %s begin time value should not be greater than t.'; $lang->productplan->featureBar['browse']['all'] = 'All'; -$lang->productplan->featureBar['browse']['unexpired'] = 'On Time'; -$lang->productplan->featureBar['browse']['overdue'] = 'Overdue'; +$lang->productplan->featureBar['browse']['unexpired'] = 'Unexpired'; +$lang->productplan->featureBar['browse']['overdue'] = 'Expired'; diff --git a/module/productplan/lang/zh-cn.php b/module/productplan/lang/zh-cn.php index 4f6b622a60..97102a30ab 100644 --- a/module/productplan/lang/zh-cn.php +++ b/module/productplan/lang/zh-cn.php @@ -17,7 +17,7 @@ $lang->productplan->edit = "编辑计划"; $lang->productplan->delete = "删除计划"; $lang->productplan->view = "计划详情"; $lang->productplan->bugSummary = "本页共 %s 个Bug"; -$lang->productplan->info = '信息'; +$lang->productplan->info = '信息'; $lang->productplan->batchEdit = '批量编辑'; $lang->productplan->batchUnlink = "批量移除"; @@ -46,14 +46,20 @@ $lang->productplan->desc = '描述'; $lang->productplan->begin = '开始日期'; $lang->productplan->end = '结束日期'; $lang->productplan->last = '上次计划'; +$lang->productplan->future = '待定'; +$lang->productplan->stories = '需求数'; +$lang->productplan->bugs = 'Bug数'; +$lang->productplan->hour = '工时'; +$lang->productplan->project = $lang->projectCommon; -$lang->productplan->endList[7] = '一星期'; -$lang->productplan->endList[14] = '两星期'; -$lang->productplan->endList[31] = '一个月'; -$lang->productplan->endList[62] = '两个月'; -$lang->productplan->endList[93] = '三个月'; -$lang->productplan->endList[186] = '半年'; -$lang->productplan->endList[365] = '一年'; +$lang->productplan->endList[7] = '一星期'; +$lang->productplan->endList[14] = '两星期'; +$lang->productplan->endList[31] = '一个月'; +$lang->productplan->endList[62] = '两个月'; +$lang->productplan->endList[93] = '三个月'; +$lang->productplan->endList[186] = '半年'; +$lang->productplan->endList[365] = '一年'; +$lang->productplan->endList[9999] = '待定'; $lang->productplan->errorNoTitle = 'ID %s 标题不能为空'; $lang->productplan->errorNoBegin = 'ID %s 开始时间不能为空'; diff --git a/module/productplan/lang/zh-tw.php b/module/productplan/lang/zh-tw.php index 2adf15a56c..71511ea2d0 100644 --- a/module/productplan/lang/zh-tw.php +++ b/module/productplan/lang/zh-tw.php @@ -17,7 +17,7 @@ $lang->productplan->edit = "編輯計劃"; $lang->productplan->delete = "刪除計劃"; $lang->productplan->view = "計劃詳情"; $lang->productplan->bugSummary = "本頁共 %s 個Bug"; -$lang->productplan->basicInfo = '基本信息'; +$lang->productplan->info = '信息'; $lang->productplan->batchEdit = '批量編輯'; $lang->productplan->batchUnlink = "批量移除"; @@ -26,6 +26,7 @@ $lang->productplan->unlinkStory = "移除需求"; $lang->productplan->batchUnlinkStory = "批量移除需求"; $lang->productplan->linkedStories = '需求'; $lang->productplan->unlinkedStories = '未關聯需求'; +$lang->productplan->updateOrder = '排序'; $lang->productplan->linkBug = "關聯Bug"; $lang->productplan->unlinkBug = "移除Bug"; @@ -45,14 +46,20 @@ $lang->productplan->desc = '描述'; $lang->productplan->begin = '開始日期'; $lang->productplan->end = '結束日期'; $lang->productplan->last = '上次計劃'; +$lang->productplan->future = '待定'; +$lang->productplan->stories = '需求數'; +$lang->productplan->bugs = 'Bug數'; +$lang->productplan->hour = '工時'; +$lang->productplan->project = $lang->projectCommon; -$lang->productplan->endList[7] = '一星期'; -$lang->productplan->endList[14] = '兩星期'; -$lang->productplan->endList[31] = '一個月'; -$lang->productplan->endList[62] = '兩個月'; -$lang->productplan->endList[93] = '三個月'; -$lang->productplan->endList[186] = '半年'; -$lang->productplan->endList[365] = '一年'; +$lang->productplan->endList[7] = '一星期'; +$lang->productplan->endList[14] = '兩星期'; +$lang->productplan->endList[31] = '一個月'; +$lang->productplan->endList[62] = '兩個月'; +$lang->productplan->endList[93] = '三個月'; +$lang->productplan->endList[186] = '半年'; +$lang->productplan->endList[365] = '一年'; +$lang->productplan->endList[9999] = '待定'; $lang->productplan->errorNoTitle = 'ID %s 標題不能為空'; $lang->productplan->errorNoBegin = 'ID %s 開始時間不能為空'; diff --git a/module/productplan/model.php b/module/productplan/model.php index 22f6b0604b..c5da6ecdce 100644 --- a/module/productplan/model.php +++ b/module/productplan/model.php @@ -15,8 +15,8 @@ class productplanModel extends model { /** * Get plan by id. - * - * @param int $planID + * + * @param int $planID * @param bool $setImgSize * @access public * @return object @@ -30,9 +30,9 @@ class productplanModel extends model } /** - * Get plans by idList - * - * @param int $planIDList + * Get plans by idList + * + * @param int $planIDList * @access public * @return array */ @@ -43,8 +43,8 @@ class productplanModel extends model /** * Get last plan. - * - * @param int $productID + * + * @param int $productID * @access public * @return void */ @@ -60,9 +60,9 @@ class productplanModel extends model } /** - * Get list - * - * @param int $product + * Get list + * + * @param int $product * @param int $branch * @param string $browseType * @param object $pager @@ -73,21 +73,39 @@ class productplanModel extends model public function getList($product = 0, $branch = 0, $browseType = 'all', $pager = null, $orderBy = 'begin_desc') { $date = date('Y-m-d'); - return $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('product')->eq($product) - ->andWhere('deleted')->eq(0) - ->beginIF(!empty($branch))->andWhere('branch')->eq($branch)->fi() - ->beginIF($browseType == 'unexpired')->andWhere('end')->gt($date)->fi() - ->beginIF($browseType == 'overdue')->andWhere('end')->le($date)->fi() + $productPlans = $this->dao->select('t1.*,t2.project')->from(TABLE_PRODUCTPLAN)->alias('t1') + ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t2.plan = t1.id and t2.product = ' . $product) + ->where('t1.product')->eq($product) + ->andWhere('t1.deleted')->eq(0) + ->beginIF(!empty($branch))->andWhere('t1.branch')->eq($branch)->fi() + ->beginIF($browseType == 'unexpired')->andWhere('t1.end')->gt($date)->fi() + ->beginIF($browseType == 'overdue')->andWhere('t1.end')->le($date)->fi() ->orderBy($orderBy) ->page($pager) - ->fetchAll(); + ->fetchAll('id'); + + if(!empty($productPlans)) + { + foreach($productPlans as $productPlan) + { + $stories = $this->dao->select('id,estimate')->from(TABLE_STORY) + ->where("CONCAT(',', plan, ',')")->like("%,{$productPlan->id},%") + ->andWhere('deleted')->eq(0) + ->fetchPairs('id', 'estimate'); + $productPlan->stories = count($stories); + $productPlan->bugs = $this->dao->select()->from(TABLE_BUG)->where("plan")->eq($productPlan->id)->andWhere('deleted')->eq(0)->count(); + $productPlan->hour = array_sum($stories); + $productPlan->projectID = $productPlan->project; + } + } + return $productPlans; } /** * Get plan pairs. - * - * @param array|int $product - * @param string $expired + * + * @param array|int $product + * @param string $expired * @access public * @return array */ @@ -117,9 +135,9 @@ class productplanModel extends model } /** - * Get plans for products - * - * @param int $products + * Get plans for products + * + * @param int $products * @access public * @return void */ @@ -133,13 +151,16 @@ class productplanModel extends model /** * Create a plan. - * + * * @access public * @return int */ public function create() { - $plan = fixer::input('post')->stripTags($this->config->productplan->editor->create['id'], $this->config->allowedTags)->remove('delta,uid')->get(); + $plan = fixer::input('post')->stripTags($this->config->productplan->editor->create['id'], $this->config->allowedTags) + ->setIF($this->post->delta == 9999 || empty($_POST['end']), 'end', '2030-01-01') + ->remove('delta,uid') + ->get(); $plan = $this->loadModel('file')->processImgURL($plan, $this->config->productplan->editor->create['id'], $this->post->uid); $this->dao->insert(TABLE_PRODUCTPLAN) ->data($plan) @@ -158,15 +179,19 @@ class productplanModel extends model /** * Update a plan - * - * @param int $planID + * + * @param int $planID * @access public * @return array */ public function update($planID) { $oldPlan = $this->dao->findByID((int)$planID)->from(TABLE_PRODUCTPLAN)->fetch(); - $plan = fixer::input('post')->stripTags($this->config->productplan->editor->edit['id'], $this->config->allowedTags)->remove('delta,uid')->get(); + $plan = fixer::input('post')->stripTags($this->config->productplan->editor->edit['id'], $this->config->allowedTags) + ->setIF($this->post->delta == 9999 || $this->post->end == '', 'end', '2030-01-01') + ->remove('delta,uid') + ->get(); + $plan = $this->loadModel('file')->processImgURL($plan, $this->config->productplan->editor->edit['id'], $this->post->uid); $this->dao->update(TABLE_PRODUCTPLAN) ->data($plan) @@ -184,8 +209,8 @@ class productplanModel extends model /** * Batch update plan. - * - * @param int $productID + * + * @param int $productID * @access public * @return array */ @@ -233,8 +258,8 @@ class productplanModel extends model /** * Link stories. - * - * @param int $planID + * + * @param int $planID * @access public * @return void */ @@ -267,9 +292,9 @@ class productplanModel extends model } /** - * Unlink story - * - * @param int $storyID + * Unlink story + * + * @param int $storyID * @access public * @return void */ @@ -284,8 +309,8 @@ class productplanModel extends model /** * Link bugs. - * - * @param int $planID + * + * @param int $planID * @access public * @return void */ diff --git a/module/productplan/view/browse.html.php b/module/productplan/view/browse.html.php index bba3dadef4..db9c272f1b 100644 --- a/module/productplan/view/browse.html.php +++ b/module/productplan/view/browse.html.php @@ -43,15 +43,19 @@ recTotal}&recPerPage={$pager->recPerPage}"; ?> - - + + session->currentProductType != 'normal'):?> - + - - - - + + + + + + + + @@ -60,18 +64,23 @@ file->replaceImgURL($plan, 'desc');?> session->currentProductType != 'normal'):?> + + + + - + - - + diff --git a/module/report/view/productsummary.html.php b/module/report/view/productsummary.html.php index 4b317d3dbc..a3b2aadd70 100644 --- a/module/report/view/productsummary.html.php +++ b/module/report/view/productsummary.html.php @@ -32,8 +32,8 @@ - - + + @@ -47,7 +47,7 @@ plans) ? count($product->plans) : 1;?> - + plans)):?> plans as $plan):?> diff --git a/module/report/view/workload.html.php b/module/report/view/workload.html.php index 87e8a599d8..d5247d417b 100644 --- a/module/report/view/workload.html.php +++ b/module/report/view/workload.html.php @@ -17,7 +17,7 @@
    -
    +
    report->dept;?> @@ -26,9 +26,9 @@
    report->taskAssignedDate;?> -
    +
    report->to;?> -
    +
    @@ -43,6 +43,9 @@
    +
    + report->assign, $assign, "class='form-control' onchange='changeParams(this)' style='width:90px'");?> +
    report->query);?>
    diff --git a/module/score/model.php b/module/score/model.php index 75331f34c1..e3d394f7a0 100644 --- a/module/score/model.php +++ b/module/score/model.php @@ -143,7 +143,7 @@ class scoreModel extends model } /* Project team user. */ - $teams = $this->dao->select('account')->from(TABLE_TEAM)->where('project')->eq($param->id)->fetchPairs(); + $teams = $this->dao->select('account')->from(TABLE_TEAM)->where('root')->eq($param->id)->andWhere('type')->eq('project')->fetchPairs(); if(!empty($teams)) { $rule['score'] = $extended['member']['close']; @@ -159,7 +159,7 @@ class scoreModel extends model } /* When the project is closed, no more user get score. */ - return true; + return true; } break; case 'search': @@ -295,7 +295,7 @@ class scoreModel extends model $notice = sprintf($this->lang->score->tips, $score, $this->app->user->score); $fullNotice = << +
    {$notice}
    diff --git a/module/score/view/rule.html.php b/module/score/view/rule.html.php index 84279cdf09..e8a3bfe157 100644 --- a/module/score/view/rule.html.php +++ b/module/score/view/rule.html.php @@ -10,64 +10,72 @@ */ ?> -
    -
    my->scoreRule; ?>
    -
    - createLink('my', 'score'), $lang->score->common, '', "class='btn btn-primary'");?> +
    +
    + +
    +
    product->name;?>product->name;?>
    action->date);?>action->date);?> action->actor);?> action->action);?> action->objectType);?> action->objectType);?> idAB);?> action->objectName;?>
    idAB);?> productplan->title);?> idAB);?> productplan->title);?> product->branch);?>product->branch);?> productplan->desc;?> productplan->begin);?> productplan->end);?>actions;?> productplan->stories;?> productplan->bugs;?> productplan->hour;?> productplan->project;?> productplan->desc;?>productplan->begin);?>productplan->end);?>actions;?>
    - + id;?> id"), $plan->title);?> branch];?> stories;?>bugs;?>hour;?>projectID)) echo html::a(helper::createLink('project', 'task', 'projectID=' . $plan->projectID), '');?>
    desc;?>
    begin;?>end;?>end == '2030-01-01' ? $lang->productplan->future : $plan->end;?> id"), '', '', "class='btn-icon' title='{$lang->project->create}'"); if(common::hasPriv('productplan', 'linkStory')) echo html::a(inlink('view', "planID=$plan->id&type=story&orderBy=id_desc&link=true"), '', '', "class='btn-icon' title='{$lang->productplan->linkStory}'"); if(common::hasPriv('productplan', 'linkBug') and $config->global->flow != 'onlyStory') echo html::a(inlink('view', "planID=$plan->id&type=bug&orderBy=id_desc&link=true"), '', '', "class='btn-icon' title='{$lang->productplan->linkBug}'"); common::printIcon('productplan', 'edit', "planID=$plan->id", $plan, 'list'); @@ -88,7 +97,7 @@
    '> + '>
    edit);?> diff --git a/module/productplan/view/edit.html.php b/module/productplan/view/edit.html.php index 2585b5532f..9bba0bad30 100644 --- a/module/productplan/view/edit.html.php +++ b/module/productplan/view/edit.html.php @@ -24,28 +24,31 @@
    - +
    - + type != 'normal'):?> - + - + - + - + @@ -53,11 +56,11 @@ - + - - @@ -117,14 +115,12 @@ ?> - + @@ -350,9 +346,7 @@ @@ -401,19 +395,19 @@ - type != 'normal'):?> - - - - - + type != 'normal'):?> + + + + + - + @@ -423,7 +417,7 @@
    - +
    diff --git a/module/project/control.php b/module/project/control.php index 46a77050f1..235947c874 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -41,7 +41,7 @@ class project extends control { if($this->app->user->account == 'guest' or commonModel::isTutorialMode()) $this->config->project->homepage = 'index'; if(!isset($this->config->project->homepage)) - { + { if($this->projects and $this->app->viewType != 'mhtml') die($this->fetch('custom', 'ajaxSetHomepage', "module=project")); $this->config->project->homepage = 'index'; @@ -251,14 +251,29 @@ class project extends control /* Get tasks and group them. */ if(empty($groupBy))$groupBy = 'story'; - $tasks = $this->loadModel('task')->getProjectTasks($projectID, $productID = 0, $status = 'all', $modules = 0, $groupBy); + $sort = $this->loadModel('common')->appendOrder($groupBy); + $tasks = $this->loadModel('task')->getProjectTasks($projectID, $productID = 0, $status = 'all', $modules = 0, $sort); $groupBy = str_replace('`', '', $groupBy); $taskLang = $this->lang->task; $groupByList = array(); $groupTasks = array(); + $groupTasks = array(); + foreach($tasks as $task) + { + $groupTasks[] = $task; + if(isset($task->children)) + { + foreach($task->children as $child) $groupTasks[] = $child; + $task->children = true; + unset($task->children); + } + } + /* Get users. */ $users = $this->loadModel('user')->getPairs('noletter'); + $tasks = $groupTasks; + $groupTasks = array(); foreach($tasks as $task) { if($groupBy == 'story') @@ -290,14 +305,6 @@ class project extends control { $groupTasks[$task->$groupBy][] = $task; } - if(isset($task->children)) - { - foreach($task->children as $child) - { - $groupTasks[$child->assignedToRealName][] = $child; - } - $task->children = true; - } } /* Process closed data when group by assignedTo. */ if($groupBy == 'assignedTo' and isset($groupTasks['Closed'])) @@ -307,7 +314,6 @@ class project extends control $groupTasks['closed'] = $closedTasks; } - /* Assign. */ $this->app->loadLang('tree'); $this->view->members = $this->project->getTeamMembers($projectID); @@ -369,7 +375,7 @@ class project extends control $this->view->title = $project->name . $this->lang->colon . $this->lang->project->importTask; $this->view->position[] = html::a(inlink('browse', "projectID=$toProject"), $project->name); $this->view->position[] = $this->lang->project->importTask; - $this->view->tasks2Imported = $tasks2Imported; + $this->view->tasks2Imported = $tasks2Imported; $this->view->projects = $projects; $this->view->projectID = $project->id; $this->view->fromProject = $fromProject; @@ -394,9 +400,6 @@ class project extends control $mails = $this->project->importBug($projectID); if(dao::isError()) die(js::error(dao::getError())); - $this->loadModel('task'); - foreach($mails as $mail) $this->task->sendmail($mail->taskID, $mail->actionID); - die(js::locate($this->createLink('project', 'importBug', "projectID=$projectID"), 'parent')); } @@ -597,16 +600,27 @@ class project extends control /* Count T B C */ $storyIdList = array_keys($stories);; - $storyTasks = $this->loadModel('task')->getStoryTaskCounts($storyIdList,$projectID); - $storyBugs = $this->loadModel('bug')->getStoryBugCounts($storyIdList,$projectID); + $storyTasks = $this->loadModel('task')->getStoryTaskCounts($storyIdList, $projectID); + $storyBugs = $this->loadModel('bug')->getStoryBugCounts($storyIdList, $projectID); $storyCases = $this->loadModel('testcase')->getStoryCaseCounts($storyIdList); + $plans = $this->project->getPlans($productID); + $allPlans = array('' => ''); + if(!empty($plans)) + { + foreach($plans as $productID => $plan) + { + $allPlans = $allPlans + $plan; + } + } + /* Assign. */ $this->view->title = $title; $this->view->position = $position; $this->view->productID = $productID; $this->view->project = $project; $this->view->stories = $stories; + $this->view->allPlans = $allPlans; $this->view->summary = $this->product->summary($stories); $this->view->orderBy = $orderBy; $this->view->type = $type; @@ -756,6 +770,7 @@ class project extends control $this->view->orderBy = $orderBy; $this->view->tasks = $this->testtask->getProjectTasks($projectID); $this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter'); + $this->view->products = $this->loadModel('product')->getPairs(); $this->display(); } @@ -820,8 +835,8 @@ class project extends control /** * Fix burn for first date. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -867,14 +882,16 @@ class project extends control * * @param string $projectID * @param string $copyProjectID + * @param int $planID * * @access public * @return void */ - public function create($projectID = '', $copyProjectID = '') + public function create($projectID = '', $copyProjectID = '', $planID = 0) { if($projectID) { + if(!empty($planID)) $this->project->linkStories($projectID); $this->view->title = $this->lang->project->tips; $this->view->tips = $this->fetch('project', 'tips', "projectID=$projectID"); $this->view->projectID = $projectID; @@ -882,12 +899,14 @@ class project extends control exit; } - $name = ''; - $code = ''; - $team = ''; - $products = array(); - $whitelist = ''; - $acl = 'open'; + $name = ''; + $code = ''; + $team = ''; + $products = array(); + $whitelist = ''; + $acl = 'open'; + $plan = new stdClass(); + $productPlan = new stdClass(); if($copyProjectID) { @@ -900,6 +919,16 @@ class project extends control $products = $this->project->getProducts($copyProjectID); } + if(!empty($planID)) + { + $plan = $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('id')->eq($planID)->fetch(); + $products = $this->dao->select('t1.id, t1.name, t1.type, t2.branch')->from(TABLE_PRODUCT)->alias('t1') + ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.product') + ->where('t1.id')->eq($plan->product) + ->fetchAll('id'); + $productPlan = $this->loadModel('productplan')->getPairs($plan->product, 0, 'unexpired'); + } + if(!empty($_POST)) { $projectID = $copyProjectID == '' ? $this->project->create() : $this->project->create($copyProjectID); @@ -907,7 +936,15 @@ class project extends control if(dao::isError()) die(js::error(dao::getError())); $this->loadModel('action')->create('project', $projectID, 'opened'); - die(js::locate($this->createLink('project', 'create', "projectID=$projectID"), 'parent')); + $url = $this->createLink('project', 'create', "projectID=$projectID"); + if(!empty($planID)) + { + die(js::confirm($this->lang->project->importPlanStory, $this->createLink('project', 'create', "projectID=$projectID©ProjectID=&planID=$planID"), $url, 'parent', 'parent')); + } + else + { + die(js::locate($url, 'parent')); + } } $this->project->setMenu($this->projects, key($this->projects)); @@ -917,12 +954,14 @@ class project extends control $this->view->projects = array('' => '') + $this->projects; $this->view->groups = $this->loadModel('group')->getPairs(); $this->view->allProducts = array(0 => '') + $this->loadModel('product')->getPairs('noclosed|nocode'); + $this->view->acl = $acl; + $this->view->plan = $plan; $this->view->name = $name; $this->view->code = $code; $this->view->team = $team; - $this->view->products = $products ; + $this->view->products = $products; + $this->view->productPlan = $productPlan; $this->view->whitelist = $whitelist; - $this->view->acl = $acl ; $this->view->copyProjectID = $copyProjectID; $this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products)); $this->display(); @@ -932,6 +971,9 @@ class project extends control * Edit a project. * * @param int $projectID + * @param string $action + * @param string $extra + * * @access public * @return void */ @@ -988,6 +1030,7 @@ class project extends control $this->view->qdUsers = $this->user->getPairs('noclosed|nodeleted|qdfirst', $project->QD); $this->view->rdUsers = $this->user->getPairs('noclosed|nodeleted|devfirst', $project->RD); $this->view->groups = $this->loadModel('group')->getPairs(); + $this->view->plans = $this->project->getPlans(array_keys($linkedProducts)); $this->view->allProducts = $allProducts; $this->view->linkedProducts = $linkedProducts; $this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($linkedProducts)); @@ -1260,10 +1303,10 @@ class project extends control /** * Kanban. - * - * @param int $projectID - * @param string $type - * @param string $orderBy + * + * @param int $projectID + * @param string $type + * @param string $orderBy * @access public * @return void */ @@ -1307,8 +1350,8 @@ class project extends control /** * Tree view. * Product - * - * @param int $projectID + * + * @param int $projectID * @param string $type * @access public * @return void @@ -1334,14 +1377,14 @@ class project extends control $this->view->projectID = $projectID; $this->view->level = $type; $this->view->tree = $tree; - $this->display(); + $this->display(); } /** * Print kanban. - * - * @param int $projectID - * @param string $orderBy + * + * @param int $projectID + * @param string $orderBy * @access public * @return void */ @@ -1356,7 +1399,7 @@ class project extends control $storySpecs = $this->story->getStorySpecs(array_keys($stories)); $order = 1; - foreach($stories as $story) $story->order = $order++; + foreach($stories as $story) $story->order = $order++; $kanbanTasks = $this->project->getKanbanTasks($projectID, "id"); $kanbanBugs = $this->loadModel('bug')->getProjectBugs($projectID); @@ -1443,13 +1486,13 @@ class project extends control $this->view->position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); $this->view->position[] = $this->lang->project->printKanban; - $this->display(); + $this->display(); } /** * Story kanban. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -1801,7 +1844,7 @@ class project extends control $this->project->unlinkStory($projectID, $storyID); /* if kanban then reload and if ajax request then send result. */ - if(isonlybody()) + if(isonlybody()) { die(js::reload('parent')); } @@ -2013,8 +2056,8 @@ class project extends control /** * Story sort. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -2073,11 +2116,11 @@ class project extends control } /** - * Export project. - * - * @param string $status - * @param int $productID - * @param string $orderBy + * Export project. + * + * @param string $status + * @param int $productID + * @param string $orderBy * @access public * @return void */ @@ -2138,8 +2181,8 @@ class project extends control /** * Kanban setting. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -2175,9 +2218,9 @@ class project extends control /** * Ajax reset kanban setting - * - * @param int $projectID - * @param string $confirm + * + * @param int $projectID + * @param string $confirm * @access public * @return void */ @@ -2201,4 +2244,26 @@ class project extends control die(js::reload('parent.parent')); } + + /** + * Import stories by plan. + * + * @param int $projectID + * @param int $planID + * + * @access public + * @return void + */ + public function importPlanStories($projectID, $planID) + { + $planStories = $planProducts = array(); + $planStory = $this->loadModel('story')->getPlanStories($planID); + if(!empty($planStory)) + { + $planStories = array_keys($planStory); + foreach($planStory as $story) $planProducts[$story->id] = $story->product; + $this->project->linkStory($projectID, $planStories, $planProducts); + } + die(js::locate(helper::createLink('project', 'story', 'projectID=' . $projectID), 'parent')); + } } diff --git a/module/project/js/common.js b/module/project/js/common.js index 67ff3bd237..b27ac9b066 100644 --- a/module/project/js/common.js +++ b/module/project/js/common.js @@ -16,8 +16,8 @@ function switchGroup(projectID, groupBy) /** * Convert a date string like 2011-11-11 to date object in js. - * - * @param string $date + * + * @param string $date * @access public * @return date */ @@ -29,9 +29,9 @@ function convertStringToDate(dateString) /** * Compute delta of two days. - * - * @param string $date1 - * @param string $date1 + * + * @param string $date1 + * @param string $date1 * @access public * @return int */ @@ -49,12 +49,12 @@ function computeDaysDelta(date1, date2) date1 += 1000 * 60 * 60 * 24; date1 = new Date(date1); } - return delta - weekEnds; + return delta - weekEnds; } /** * Compute work days. - * + * * @access public * @return void */ @@ -80,12 +80,12 @@ function computeWorkDays(currentID) endDate = $('#end').val(); } - if(beginDate && endDate) + if(beginDate && endDate) { if(isBactchEdit) $('#dayses\\[' + index + '\\]').val(computeDaysDelta(beginDate, endDate)); if(!isBactchEdit) $('#days').val(computeDaysDelta(beginDate, endDate)); } - else if($('input[checked="true"]').val()) + else if($('input[checked="true"]').val()) { computeEndDate(); } @@ -93,8 +93,8 @@ function computeWorkDays(currentID) /** * Compute the end date for project. - * - * @param int $delta + * + * @param int $delta * @access public * @return void */ @@ -117,8 +117,8 @@ function computeEndDate(delta) /** * Load branches. - * - * @param int $product + * + * @param int $product * @access public * @return void */ @@ -134,20 +134,20 @@ function loadBranches(product) $product.trigger("chosen:updated"); return false; } - }) + }); if($('#productsBox .input-group:last select:first').val() != 0) { var length = $('#productsBox .input-group').size(); $('#productsBox .row').append('
    ' + $('#productsBox .col-sm-3:last').html() + '
    '); - if($('#productsBox .input-group:last select').size() >= 2)$('#productsBox .input-group:last select:last').remove(); + if($('#productsBox .input-group:last select').size() >= 2) $('#productsBox .input-group:last select:last').remove(); $('#productsBox .input-group:last .chosen-container').remove(); $('#productsBox .input-group:last select:first').attr('name', 'products[' + length + ']').attr('id', 'products' + length); $('#productsBox .input-group:last .chosen').chosen(defaultChosenOptions); } var $inputgroup = $(product).closest('.input-group'); - if($inputgroup.find('select').size() >= 2)$inputgroup.find('select:last').remove(); + if($inputgroup.find('select').size() >= 2) $inputgroup.find('select:last').remove(); var index = $inputgroup.find('select:first').attr('id').replace('products' , ''); $.get(createLink('branch', 'ajaxGetBranches', "productID=" + $(product).val()), function(data) { @@ -156,12 +156,30 @@ function loadBranches(product) $inputgroup.append(data); $inputgroup.find('select:last').attr('name', 'branch[' + index + ']').attr('id', 'branch' + index).css('width', '80px'); } - }) + }); + + var productID = $(product).val(); + + if(productID == 0 || productID != $(product).data('last')) $("#plan" + $(product).data('last')).remove(); + + if(productID != 0 && $("#plan" + productID).length == 0) + { + $(product).data("last", productID); + $.get(createLink('product', 'ajaxGetPlans', "productID=" + productID), function(data) + { + if(data) + { + $("#plansBox .row").append('
    ' + data + '
    '); + $("#plan" + $(product).val()).find('select').attr('name', 'plans[' + productID + ']').attr('id', 'plans' + productID); + } + }); + } } + function loadBranch(){} /* Auto compute the work days. */ -$(function() +$(function() { if(typeof(replaceID) != 'undefined') { @@ -195,8 +213,8 @@ $(function() $('tr.parent-'+id).hide(); $toggleIcon.removeClass('icon-double-angle-up').addClass('icon-double-angle-down'); } - + e.stopPropagation(); e.preventDefault(); }); -}) +}); diff --git a/module/project/js/create.js b/module/project/js/create.js index b4f739c7c4..cec75c4dff 100644 --- a/module/project/js/create.js +++ b/module/project/js/create.js @@ -8,10 +8,10 @@ $(function() $('#cpmBtn').click(function(){$('#copyProjectModal').modal('show')}); $('#copyProjects a').click(function(){setCopyProject($(this).data('id')); $('#copyProjectModal').modal('hide')}); var typeWidth = $('#type').closest('td').width(); - $('#productsBox .col-sm-3').width(typeWidth); + $('#productsBox .col-sm-3,#plansBox .col-sm-3').width(typeWidth); $(document).on('change', "#productsBox select", function() { - $('#productsBox .col-sm-3').width(typeWidth); + $('#productsBox .col-sm-3,#plansBox .col-sm-3').width(typeWidth); }); $('#begin').on('change', function() { @@ -37,3 +37,4 @@ function showTypeTips() $('.type-tips').hide(); } } + diff --git a/module/project/js/kanban.js b/module/project/js/kanban.js index 85e1e007e5..2628595ad7 100644 --- a/module/project/js/kanban.js +++ b/module/project/js/kanban.js @@ -184,6 +184,10 @@ $(function() } } + $("#kanbanHeader thead tr th").each(function(i) + { + $(this).width($('#kanbanWrapper thead tr th').eq(i).width()); + }); var fixH = $("#kanbanHeader").offset().top; $(window).scroll(function() { diff --git a/module/project/js/story.js b/module/project/js/story.js index f9290a4e9f..c05d3acb30 100644 --- a/module/project/js/story.js +++ b/module/project/js/story.js @@ -24,6 +24,17 @@ $(function() $('#branch' + branchID).addClass('active'); $(document).on('click', "#storyList tbody tr", function(){showCheckedSummary();}); $(document).on('change', "#storyList :checkbox", function(){showCheckedSummary();}); + + $("a[data-toggle='linkStoryByPlan']").click(function(){$('#linkStoryByPlan').modal('show')}) + + $('#toTaskButton').on('click', function () + { + var planID = $('#plan').val(); + if(planID) + { + parent.location.href = createLink('project', 'importPlanStories', 'projectID=' + projectID + '&planID=' + planID); + } + }) }); function showCheckedSummary() diff --git a/module/project/lang/en.php b/module/project/lang/en.php index 310f4b6e45..d59049ef8b 100644 --- a/module/project/lang/en.php +++ b/module/project/lang/en.php @@ -17,43 +17,43 @@ $lang->project->name = 'Name'; $lang->project->code = 'Alias'; $lang->project->begin = 'Begin'; $lang->project->end = 'End'; -$lang->project->dateRange = 'Time Frame'; +$lang->project->dateRange = 'Duration'; $lang->project->to = 'To'; $lang->project->days = 'Man-Day'; $lang->project->day = 'day'; -$lang->project->workHour = 'Hour'; +$lang->project->workHour = 'Hour(s)'; $lang->project->status = 'Status'; $lang->project->desc = 'Desc'; $lang->project->owner = 'Owner'; -$lang->project->PO = $lang->productCommon . ' Owner'; -$lang->project->PM = $lang->projectCommon . ' Manager'; -$lang->project->QD = 'Quality Director'; -$lang->project->RD = 'Release Director'; +$lang->project->PO = 'PO'; +$lang->project->PM = 'PM'; +$lang->project->QD = 'QA Manager'; +$lang->project->RD = 'Release Manager'; $lang->project->acl = 'Access Control'; $lang->project->teamname = 'Team Name'; $lang->project->order = "Sort {$lang->projectCommon}"; -$lang->project->products = "Link {$lang->productCommon}"; +$lang->project->products = "Linked {$lang->productCommon}"; $lang->project->whitelist = 'Whitelist'; -$lang->project->totalEstimate = 'Est.'; -$lang->project->totalConsumed = 'Consumed'; -$lang->project->totalLeft = 'Total Remained'; -$lang->project->Left = 'Remained'; +$lang->project->totalEstimate = 'Est.(h)'; +$lang->project->totalConsumed = 'Cost'; +$lang->project->totalLeft = 'Left'; +$lang->project->Left = 'Left'; $lang->project->progress = 'Progress'; -$lang->project->hours = 'Estimate %s, Consumed %s, Remained %s'; +$lang->project->hours = '%s Estimate, %s Cost, %s Left.'; $lang->project->viewBug = 'Bugs'; $lang->project->noProduct = "No {$lang->productCommon}"; $lang->project->createStory = "Create Story"; $lang->project->all = 'All'; -$lang->project->undone = 'Undone'; +$lang->project->undone = 'Unfinished'; $lang->project->unclosed = 'Unclosed'; -$lang->project->typeDesc = 'No story, bug, build, testtask and burndown allowed in OPS'; +$lang->project->typeDesc = 'No story, bug, build, test task or burndown is allowed in OPS'; $lang->project->mine = 'My Responsibility: '; $lang->project->other = 'Other:'; $lang->project->deleted = 'Deleted'; $lang->project->delayed = 'Delayed'; $lang->project->product = $lang->project->products; -$lang->project->readjustTime = 'Readjust project time for begin and end'; -$lang->project->readjustTask = 'Readjust task start date and deadline'; +$lang->project->readjustTime = 'Adjust project begin and end time'; +$lang->project->readjustTask = 'Adjust task start date and deadline'; $lang->project->start = 'Start'; $lang->project->activate = 'Activate'; @@ -77,12 +77,12 @@ $lang->project->endList[365] = '1 Year'; $lang->team = new stdclass(); $lang->team->account = 'Account'; $lang->team->role = 'Role'; -$lang->team->join = 'Joined Date'; +$lang->team->join = 'Joined'; $lang->team->hours = 'Hour/Day'; $lang->team->days = 'Workdays'; $lang->team->totalHours = 'Total'; -$lang->team->limited = 'limited User'; +$lang->team->limited = 'Limited User'; $lang->team->limitedList['no'] = 'No'; $lang->team->limitedList['yes'] = 'Yes'; @@ -95,53 +95,57 @@ $lang->project->statusList['doing'] = 'Doing'; $lang->project->statusList['suspended'] = 'Suspend'; $lang->project->statusList['done'] = 'Done'; -$lang->project->aclList['open'] = "Default (You have access to {$lang->projectCommon}, if you can view it.)"; -$lang->project->aclList['private'] = 'Private (Only team members can access to it.)'; -$lang->project->aclList['custom'] = 'Whitelist (Team members and the whitelist members have access to it.)'; +$lang->project->aclList['open'] = "Default (Those who can visit ‘project view’ can access.)"; +$lang->project->aclList['private'] = 'Private (Only team members can access.)'; +$lang->project->aclList['custom'] = 'Whitelist (Team members and the whitelist members can access.)'; /* 方法列表。*/ -$lang->project->index = "Home"; -$lang->project->task = 'Tasks'; -$lang->project->groupTask = 'View by'; -$lang->project->story = 'Stories'; -$lang->project->bug = 'Bugs'; -$lang->project->dynamic = 'Dynamic'; -$lang->project->build = 'Builds'; -$lang->project->testtask = 'Test Tasks'; -$lang->project->burn = 'Burndown'; -$lang->project->baseline = 'Base Line'; -$lang->project->computeBurn = 'Update'; -$lang->project->burnData = 'Burndown Data'; -$lang->project->fixFirst = 'Edit 1st Day Data'; -$lang->project->team = 'Team Member'; -$lang->project->doc = 'Doc'; -$lang->project->manageProducts = 'Link ' . $lang->productCommon; -$lang->project->linkStory = 'Linked Story'; -$lang->project->unlinkStoryTasks = 'Unlinked'; -$lang->project->linkedProducts = 'Linked Products'; -$lang->project->unlinkedProducts = 'Unlinked Products'; -$lang->project->view = "Info"; -$lang->project->create = "Add"; -$lang->project->copy = "Copy {$lang->projectCommon}"; -$lang->project->delete = "Delete"; -$lang->project->browse = "Browse"; -$lang->project->edit = "Edit"; -$lang->project->batchEdit = "Batch Edit"; -$lang->project->manageMembers = 'Manange Team'; -$lang->project->unlinkMember = 'Unlink Member'; -$lang->project->unlinkStory = 'Unlink Story'; -$lang->project->batchUnlinkStory = 'Batch Unlink Story'; -$lang->project->importTask = 'Import Task'; -$lang->project->importBug = 'Import Bug'; -$lang->project->updateOrder = 'Order'; -$lang->project->tree = 'Tree'; -$lang->project->storyKanban = 'Story Kanban'; -$lang->project->storySort = 'Story Sort'; +$lang->project->index = "Home"; +$lang->project->task = 'Tasks'; +$lang->project->groupTask = 'View by Group'; +$lang->project->story = 'Stories'; +$lang->project->bug = 'Bugs'; +$lang->project->dynamic = 'Dynamic'; +$lang->project->build = 'Builds'; +$lang->project->testtask = 'Test Tasks'; +$lang->project->burn = 'Burndown'; +$lang->project->baseline = 'Base Line'; +$lang->project->computeBurn = 'Update'; +$lang->project->burnData = 'Burndown Data'; +$lang->project->fixFirst = 'Edit 1st Day Man-hour'; +$lang->project->team = 'Team Member'; +$lang->project->doc = 'Doc'; +$lang->project->manageProducts = 'Link ' . $lang->productCommon; +$lang->project->linkStory = 'Linked Story'; +$lang->project->linkStoryByPlan = 'Linked Story From Plan'; +$lang->project->linkPlan = 'Linked Plan'; +$lang->project->unlinkStoryTasks = 'Unlinked'; +$lang->project->linkedProducts = 'Linked Products'; +$lang->project->unlinkedProducts = 'Unlinked Products'; +$lang->project->view = "Overview"; +$lang->project->create = "Create Project"; +$lang->project->copy = "Copy {$lang->projectCommon}"; +$lang->project->delete = "Delete"; +$lang->project->browse = "Browse"; +$lang->project->edit = "Edit"; +$lang->project->batchEdit = "Batch Edit"; +$lang->project->manageMembers = 'Manange Team'; +$lang->project->unlinkMember = 'Unlink Member'; +$lang->project->unlinkStory = 'Unlink Story'; +$lang->project->batchUnlinkStory = 'Batch Unlink Story'; +$lang->project->importTask = 'Import Task'; +$lang->project->importPlanStories = 'Link Story By Plan'; +$lang->project->importBug = 'Import Bug'; +$lang->project->updateOrder = 'Order'; +$lang->project->tree = 'Tree'; +$lang->project->storyKanban = 'Story Kanban'; +$lang->project->storySort = 'Sort Story'; +$lang->project->importPlanStory = 'Create ' . $lang->projectCommon . ' success!\nImport the stories with the plan?'; /* 分组浏览。*/ $lang->project->allTasks = 'All'; -$lang->project->assignedToMe = 'Assigned to Me'; -$lang->project->myInvolved = 'My Involved'; +$lang->project->assignedToMe = 'My'; +$lang->project->myInvolved = 'Involved'; $lang->project->statusSelects[''] = 'More'; $lang->project->statusSelects['wait'] = 'Wait'; @@ -167,7 +171,7 @@ $lang->project->groupFilter['pri']['noset'] = 'Not set'; $lang->project->groupFilter['assignedTo']['undone'] = 'Pending'; $lang->project->groupFilter['assignedTo']['all'] = $lang->project->all; -$lang->project->byQuery = 'Search'; +$lang->project->byQuery = 'Search'; /* 查询条件列表。*/ $lang->project->allProject = "All {$lang->projectCommon}"; @@ -176,14 +180,14 @@ $lang->project->aboveAllProject = "All the above {$lang->projectCommon}"; /* 页面提示。*/ $lang->project->selectProject = "Select {$lang->projectCommon}"; -$lang->project->beginAndEnd = 'Time Frame'; -$lang->project->lblStats = 'Hour Report'; -$lang->project->stats = '%s Hour(s) available, %s Hour(s) Estimated, %s Hour(s) Consumed, %s Hour(s) Remained.'; -$lang->project->taskSummary = " %s Tasks on this page, %s Wait, %s Doing. %s Hour(s) Estimated, %s Hour(s) Consumed, %s Hour(s) Remained."; -$lang->project->checkedSummary = " %total% Checked, %wait% Wait, %doing% Doing, %estimate% Hour(s) Estimated, %consumed% Hour(s) Consumed, %left% Hour(s) Remained."; +$lang->project->beginAndEnd = 'Duration'; +$lang->project->lblStats = 'Man-Hour Summary(h) : '; +$lang->project->stats = '%s Available, %s Total Estimated, %s Cost, %s Left.'; +$lang->project->taskSummary = "Tasks on this page : %s Total, %s Wait, %s Doing;     Hours : %s Est., %s Cost, %s Left."; +$lang->project->checkedSummary = " %total% Checked, %wait% Wait, %doing% Doing; Hours: %estimate% Est., %consumed% Cost, %left% Left."; $lang->project->memberHours = "%s has %s Hour(s) available "; -$lang->project->groupSummary = "%s Tasks in this group, Wait %s, Doing %s. %s Hour(s) Estimated , %s Hour(s) Consumed, %s Hour(s) Remained."; -$lang->project->groupSummaryAB = "Total Tasks %s, Wait %s, Doing %s.
    %s Hour(s) Estimated, %s Hour(s) Consumed,%s Hour(s) Remained."; +$lang->project->groupSummary = "%s Tasks in this group, Wait %s, Doing %s. %s Hour(s) Estimated , %s Hour(s) Cost, %s Hour(s) Left."; +$lang->project->groupSummaryAB = "Tasks:%s Total,%s Wait, %s Doing.
    Hours: %s Est., %s Cost,%s Left."; $lang->project->noTimeSummary = " %s Tasks in this group, Wait %s, Doing %s."; $lang->project->wbs = "Decompose Task"; $lang->project->batchWBS = "Batch Decompose"; @@ -202,7 +206,7 @@ $lang->project->copyNoProject = "No {$lang->projectCommon} can be duplicated." $lang->project->copyFromProject = "Duplicate from {$lang->projectCommon} %s"; $lang->project->cancelCopy = 'Cancel Duplication'; $lang->project->byPeriod = 'By Time'; -$lang->project->byUser = 'By User'; +$lang->project->byUser = 'ByUser'; /* 交互提示。*/ $lang->project->confirmDelete = "Do you want to delete {$lang->projectCommon}[%s]?"; @@ -220,7 +224,7 @@ $lang->project->goback = "Go Back"; $lang->project->noweekend = 'Without Weekend'; $lang->project->withweekend = 'With Weekend'; $lang->project->interval = 'Intervals'; -$lang->project->fixFirstWithLeft = 'Modify the left time'; +$lang->project->fixFirstWithLeft = 'Modify the left'; /* 统计。*/ $lang->project->charts = new stdclass(); @@ -236,8 +240,8 @@ $lang->project->charts->burn->graph->rotateNames = 1; $lang->project->charts->burn->graph->showValues = 0; $lang->project->placeholder = new stdclass(); -$lang->project->placeholder->code = "{$lang->projectCommon} Code"; -$lang->project->placeholder->totalLeft = 'Hour(s) remained at the beginning of Project'; +$lang->project->placeholder->code = 'Project abbreviation in team'; +$lang->project->placeholder->totalLeft = 'Hour(s) remained at Project Starting'; $lang->project->selectGroup = new stdclass(); $lang->project->selectGroup->done = '(Done)'; @@ -255,7 +259,7 @@ $lang->project->resetKanban = "Reset Setting"; $lang->project->printKanban = "Print Kanban"; $lang->project->bugList = "Bugs"; -$lang->project->kanbanHideCols = 'Kanban hidden has been closed and canceled columns'; +$lang->project->kanbanHideCols = 'hide closed and canceled columns in Kanban'; $lang->project->kanbanShowOption = 'Display folding information'; $lang->project->kanbanColsColor = 'Custom color for Kanban column'; @@ -279,14 +283,14 @@ $lang->project->featureBar['task']['all'] = $lang->project->allTasks; $lang->project->featureBar['task']['assignedtome'] = $lang->project->assignedToMe; $lang->project->featureBar['task']['myinvolved'] = $lang->project->myInvolved; $lang->project->featureBar['task']['delayed'] = 'Delayed'; -$lang->project->featureBar['task']['needconfirm'] = 'Story Changed'; +$lang->project->featureBar['task']['needconfirm'] = 'StoryChanged'; $lang->project->featureBar['task']['status'] = $lang->project->statusSelects['']; $lang->project->treeLevel = array(); -$lang->project->treeLevel['root'] = 'Show Root'; -$lang->project->treeLevel['story'] = 'Show Story'; -$lang->project->treeLevel['task'] = 'Show Task'; -$lang->project->treeLevel['all'] = 'Show All'; +$lang->project->treeLevel['root'] = 'Collapse All'; +$lang->project->treeLevel['story'] = 'Show Story'; +$lang->project->treeLevel['task'] = 'Show Task'; +$lang->project->treeLevel['all'] = 'Expand All'; global $config; if($config->global->flow == 'onlyTask') diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php index 44a1840780..49fea0814b 100644 --- a/module/project/lang/zh-cn.php +++ b/module/project/lang/zh-cn.php @@ -34,9 +34,9 @@ $lang->project->teamname = '团队名称'; $lang->project->order = $lang->projectCommon . '排序'; $lang->project->products = '相关' . $lang->productCommon; $lang->project->whitelist = '分组白名单'; -$lang->project->totalEstimate = '总预计'; -$lang->project->totalConsumed = '总消耗'; -$lang->project->totalLeft = '总剩余'; +$lang->project->totalEstimate = '预计'; +$lang->project->totalConsumed = '消耗'; +$lang->project->totalLeft = '剩余'; $lang->project->Left = '剩余'; $lang->project->progress = '进度'; $lang->project->hours = '预计 %s 消耗 %s 剩余 %s'; @@ -66,13 +66,13 @@ $lang->project->typeList['sprint'] = "短期$lang->projectCommon"; $lang->project->typeList['waterfall'] = "长期$lang->projectCommon"; $lang->project->typeList['ops'] = "运维$lang->projectCommon"; -$lang->project->endList[7] = '一星期'; -$lang->project->endList[14] = '两星期'; -$lang->project->endList[31] = '一个月'; -$lang->project->endList[62] = '两个月'; -$lang->project->endList[93] = '三个月'; -$lang->project->endList[186] = '半年'; -$lang->project->endList[365] = '一年'; +$lang->project->endList[7] = '一星期'; +$lang->project->endList[14] = '两星期'; +$lang->project->endList[31] = '一个月'; +$lang->project->endList[62] = '两个月'; +$lang->project->endList[93] = '三个月'; +$lang->project->endList[186] = '半年'; +$lang->project->endList[365] = '一年'; $lang->team = new stdclass(); $lang->team->account = '用户'; @@ -100,43 +100,47 @@ $lang->project->aclList['private'] = "私有{$lang->projectCommon}(只有{$lang- $lang->project->aclList['custom'] = "自定义白名单(团队成员和白名单的成员可以访问)"; /* 方法列表。*/ -$lang->project->index = "{$lang->projectCommon}首页"; -$lang->project->task = '任务列表'; -$lang->project->groupTask = '分组浏览任务'; -$lang->project->story = '需求列表'; -$lang->project->bug = 'Bug列表'; -$lang->project->dynamic = '动态'; -$lang->project->build = '版本列表'; -$lang->project->testtask = '测试任务'; -$lang->project->burn = '燃尽图'; -$lang->project->baseline = '基准线'; -$lang->project->computeBurn = '更新'; -$lang->project->burnData = '燃尽图数据'; -$lang->project->fixFirst = '修改首天工时'; -$lang->project->team = '团队成员'; -$lang->project->doc = '文档列表'; -$lang->project->manageProducts = '关联' . $lang->productCommon; -$lang->project->linkStory = '关联需求'; -$lang->project->unlinkStoryTasks = '未关联需求任务'; -$lang->project->linkedProducts = '已关联'; -$lang->project->unlinkedProducts = '未关联'; -$lang->project->view = "{$lang->projectCommon}概况"; -$lang->project->create = "添加{$lang->projectCommon}"; -$lang->project->copy = "复制{$lang->projectCommon}"; -$lang->project->delete = "删除{$lang->projectCommon}"; -$lang->project->browse = "浏览{$lang->projectCommon}"; -$lang->project->edit = "编辑{$lang->projectCommon}"; -$lang->project->batchEdit = "批量编辑"; -$lang->project->manageMembers = '团队管理'; -$lang->project->unlinkMember = '移除成员'; -$lang->project->unlinkStory = '移除需求'; -$lang->project->batchUnlinkStory = '批量移除需求'; -$lang->project->importTask = '转入任务'; -$lang->project->importBug = '导入Bug'; -$lang->project->updateOrder = '排序'; -$lang->project->tree = '树状图'; -$lang->project->storyKanban = '需求看板'; -$lang->project->storySort = '需求排序'; +$lang->project->index = "{$lang->projectCommon}首页"; +$lang->project->task = '任务列表'; +$lang->project->groupTask = '分组浏览任务'; +$lang->project->story = '需求列表'; +$lang->project->bug = 'Bug列表'; +$lang->project->dynamic = '动态'; +$lang->project->build = '版本列表'; +$lang->project->testtask = '测试任务'; +$lang->project->burn = '燃尽图'; +$lang->project->baseline = '基准线'; +$lang->project->computeBurn = '更新'; +$lang->project->burnData = '燃尽图数据'; +$lang->project->fixFirst = '修改首天工时'; +$lang->project->team = '团队成员'; +$lang->project->doc = '文档列表'; +$lang->project->manageProducts = '关联' . $lang->productCommon; +$lang->project->linkStory = '关联需求'; +$lang->project->linkStoryByPlan = '按照计划关联'; +$lang->project->linkPlan = '关联计划'; +$lang->project->unlinkStoryTasks = '未关联需求任务'; +$lang->project->linkedProducts = '已关联'; +$lang->project->unlinkedProducts = '未关联'; +$lang->project->view = "{$lang->projectCommon}概况"; +$lang->project->create = "添加{$lang->projectCommon}"; +$lang->project->copy = "复制{$lang->projectCommon}"; +$lang->project->delete = "删除{$lang->projectCommon}"; +$lang->project->browse = "浏览{$lang->projectCommon}"; +$lang->project->edit = "编辑{$lang->projectCommon}"; +$lang->project->batchEdit = "批量编辑"; +$lang->project->manageMembers = '团队管理'; +$lang->project->unlinkMember = '移除成员'; +$lang->project->unlinkStory = '移除需求'; +$lang->project->batchUnlinkStory = '批量移除需求'; +$lang->project->importTask = '转入任务'; +$lang->project->importPlanStories = '按计划关联需求'; +$lang->project->importBug = '导入Bug'; +$lang->project->updateOrder = '排序'; +$lang->project->tree = '树状图'; +$lang->project->storyKanban = '需求看板'; +$lang->project->storySort = '需求排序'; +$lang->project->importPlanStory = '创建' . $lang->projectCommon . '成功!\n是否导入计划关联的相关需求?'; /* 分组浏览。*/ $lang->project->allTasks = '所有'; @@ -283,10 +287,10 @@ $lang->project->featureBar['task']['needconfirm'] = '需求变动'; $lang->project->featureBar['task']['status'] = $lang->project->statusSelects['']; $lang->project->treeLevel = array(); -$lang->project->treeLevel['root'] = '全部折叠'; -$lang->project->treeLevel['story'] = '显示需求'; -$lang->project->treeLevel['task'] = '显示任务'; -$lang->project->treeLevel['all'] = '全部展开'; +$lang->project->treeLevel['root'] = '全部折叠'; +$lang->project->treeLevel['story'] = '显示需求'; +$lang->project->treeLevel['task'] = '显示任务'; +$lang->project->treeLevel['all'] = '全部展开'; global $config; if($config->global->flow == 'onlyTask') diff --git a/module/project/lang/zh-tw.php b/module/project/lang/zh-tw.php index b534e98c07..7d9f554aa3 100644 --- a/module/project/lang/zh-tw.php +++ b/module/project/lang/zh-tw.php @@ -34,15 +34,15 @@ $lang->project->teamname = '團隊名稱'; $lang->project->order = $lang->projectCommon . '排序'; $lang->project->products = '相關' . $lang->productCommon; $lang->project->whitelist = '分組白名單'; -$lang->project->totalEstimate = '總預計'; -$lang->project->totalConsumed = '總消耗'; -$lang->project->totalLeft = '總剩餘'; +$lang->project->totalEstimate = '預計'; +$lang->project->totalConsumed = '消耗'; +$lang->project->totalLeft = '剩餘'; $lang->project->Left = '剩餘'; $lang->project->progress = '進度'; $lang->project->hours = '預計 %s 消耗 %s 剩餘 %s'; $lang->project->viewBug = '查看bug'; $lang->project->noProduct = "無{$lang->productCommon}{$lang->projectCommon}"; -$lang->project->createStory = "新增需求"; +$lang->project->createStory = "添加需求"; $lang->project->all = '所有'; $lang->project->undone = '未完成'; $lang->project->unclosed = '未關閉'; @@ -66,13 +66,13 @@ $lang->project->typeList['sprint'] = "短期$lang->projectCommon"; $lang->project->typeList['waterfall'] = "長期$lang->projectCommon"; $lang->project->typeList['ops'] = "運維$lang->projectCommon"; -$lang->project->endList[7] = '一星期'; -$lang->project->endList[14] = '兩星期'; -$lang->project->endList[31] = '一個月'; -$lang->project->endList[62] = '兩個月'; -$lang->project->endList[93] = '三個月'; -$lang->project->endList[186] = '半年'; -$lang->project->endList[365] = '一年'; +$lang->project->endList[7] = '一星期'; +$lang->project->endList[14] = '兩星期'; +$lang->project->endList[31] = '一個月'; +$lang->project->endList[62] = '兩個月'; +$lang->project->endList[93] = '三個月'; +$lang->project->endList[186] = '半年'; +$lang->project->endList[365] = '一年'; $lang->team = new stdclass(); $lang->team->account = '用戶'; @@ -100,47 +100,52 @@ $lang->project->aclList['private'] = "私有{$lang->projectCommon}(只有{$lang- $lang->project->aclList['custom'] = "自定義白名單(團隊成員和白名單的成員可以訪問)"; /* 方法列表。*/ -$lang->project->index = "{$lang->projectCommon}首頁"; -$lang->project->task = '任務列表'; -$lang->project->groupTask = '分組瀏覽任務'; -$lang->project->story = '需求列表'; -$lang->project->bug = 'Bug列表'; -$lang->project->dynamic = '動態'; -$lang->project->build = '版本列表'; -$lang->project->testtask = '測試任務'; -$lang->project->burn = '燃盡圖'; -$lang->project->baseline = '基準綫'; -$lang->project->computeBurn = '更新'; -$lang->project->burnData = '燃盡圖數據'; -$lang->project->fixFirst = '修改首天工時'; -$lang->project->team = '團隊成員'; -$lang->project->doc = '文檔列表'; -$lang->project->manageProducts = '關聯' . $lang->productCommon; -$lang->project->linkStory = '關聯需求'; -$lang->project->unlinkStoryTasks = '未關聯需求任務'; -$lang->project->linkedProducts = '已關聯'; -$lang->project->unlinkedProducts = '未關聯'; -$lang->project->view = "{$lang->projectCommon}概況"; -$lang->project->create = "添加{$lang->projectCommon}"; -$lang->project->copy = "複製{$lang->projectCommon}"; -$lang->project->delete = "刪除{$lang->projectCommon}"; -$lang->project->browse = "瀏覽{$lang->projectCommon}"; -$lang->project->edit = "編輯{$lang->projectCommon}"; -$lang->project->batchEdit = "批量編輯"; -$lang->project->manageMembers = '團隊管理'; -$lang->project->unlinkMember = '移除成員'; -$lang->project->unlinkStory = '移除需求'; -$lang->project->batchUnlinkStory = '批量移除需求'; -$lang->project->importTask = '轉入任務'; -$lang->project->importBug = '導入Bug'; -$lang->project->updateOrder = '排序'; -$lang->project->tree = '樹狀圖'; -$lang->project->storyKanban = '需求看板'; -$lang->project->storySort = '需求排序'; +$lang->project->index = "{$lang->projectCommon}首頁"; +$lang->project->task = '任務列表'; +$lang->project->groupTask = '分組瀏覽任務'; +$lang->project->story = '需求列表'; +$lang->project->bug = 'Bug列表'; +$lang->project->dynamic = '動態'; +$lang->project->build = '版本列表'; +$lang->project->testtask = '測試任務'; +$lang->project->burn = '燃盡圖'; +$lang->project->baseline = '基準綫'; +$lang->project->computeBurn = '更新'; +$lang->project->burnData = '燃盡圖數據'; +$lang->project->fixFirst = '修改首天工時'; +$lang->project->team = '團隊成員'; +$lang->project->doc = '文檔列表'; +$lang->project->manageProducts = '關聯' . $lang->productCommon; +$lang->project->linkStory = '關聯需求'; +$lang->project->linkStoryByPlan = '按照計劃關聯'; +$lang->project->linkPlan = '關聯計劃'; +$lang->project->unlinkStoryTasks = '未關聯需求任務'; +$lang->project->linkedProducts = '已關聯'; +$lang->project->unlinkedProducts = '未關聯'; +$lang->project->view = "{$lang->projectCommon}概況"; +$lang->project->create = "添加{$lang->projectCommon}"; +$lang->project->copy = "複製{$lang->projectCommon}"; +$lang->project->delete = "刪除{$lang->projectCommon}"; +$lang->project->browse = "瀏覽{$lang->projectCommon}"; +$lang->project->edit = "編輯{$lang->projectCommon}"; +$lang->project->batchEdit = "批量編輯"; +$lang->project->manageMembers = '團隊管理'; +$lang->project->unlinkMember = '移除成員'; +$lang->project->unlinkStory = '移除需求'; +$lang->project->batchUnlinkStory = '批量移除需求'; +$lang->project->importTask = '轉入任務'; +$lang->project->importPlanStories = '按計劃關聯需求'; +$lang->project->importBug = '導入Bug'; +$lang->project->updateOrder = '排序'; +$lang->project->tree = '樹狀圖'; +$lang->project->storyKanban = '需求看板'; +$lang->project->storySort = '需求排序'; +$lang->project->importPlanStory = '創建' . $lang->projectCommon . '成功!\n是否導入計劃關聯的相關需求?'; /* 分組瀏覽。*/ -$lang->project->allTasks = '所有'; -$lang->project->assignedToMe = '指派給我'; +$lang->project->allTasks = '所有'; +$lang->project->assignedToMe = '指派給我'; +$lang->project->myInvolved = '由我參與'; $lang->project->statusSelects[''] = '更多'; $lang->project->statusSelects['wait'] = '未開始'; @@ -179,6 +184,7 @@ $lang->project->beginAndEnd = '起止時間'; $lang->project->lblStats = '工時統計'; $lang->project->stats = '可用工時%s工時,總共預計%s工時,已經消耗%s工時,預計剩餘%s工時'; $lang->project->taskSummary = "本頁共 %s 個任務,未開始 %s,進行中 %s,總預計%s工時,已消耗%s工時,剩餘%s工時。"; +$lang->project->checkedSummary = "選中 %total% 個任務,未開始 %wait%,進行中 %doing%,總預計%estimate%工時,已消耗%consumed%工時,剩餘%left%工時。"; $lang->project->memberHours = "%s共有 %s 個可用工時,"; $lang->project->groupSummary = "本組共 %s 個任務,未開始 %s,進行中 %s,總預計%s工時,已消耗%s工時,剩餘%s工時。"; $lang->project->groupSummaryAB = "總任務%s ,未開始%s,進行中%s。
    總預計%s,已消耗%s,剩餘%s。"; @@ -213,7 +219,7 @@ $lang->project->tips = '提示'; $lang->project->afterInfo = "{$lang->projectCommon}添加成功,您現在可以進行以下操作:"; $lang->project->setTeam = '設置團隊'; $lang->project->linkStory = '關聯需求'; -$lang->project->createTask = '添加任務'; +$lang->project->createTask = '創建任務'; $lang->project->goback = "返回任務列表"; $lang->project->noweekend = '去除周末'; $lang->project->withweekend = '顯示周末'; @@ -275,15 +281,16 @@ $lang->printKanban->typeList['increment'] = '增量'; $lang->project->featureBar['task']['unclosed'] = $lang->project->unclosed; $lang->project->featureBar['task']['all'] = $lang->project->allTasks; $lang->project->featureBar['task']['assignedtome'] = $lang->project->assignedToMe; +$lang->project->featureBar['task']['myinvolved'] = $lang->project->myInvolved; $lang->project->featureBar['task']['delayed'] = '已延期'; $lang->project->featureBar['task']['needconfirm'] = '需求變動'; $lang->project->featureBar['task']['status'] = $lang->project->statusSelects['']; $lang->project->treeLevel = array(); -$lang->project->treeLevel['root'] = '全部摺疊'; -$lang->project->treeLevel['story'] = '顯示需求'; -$lang->project->treeLevel['task'] = '顯示任務'; -$lang->project->treeLevel['all'] = '全部展開'; +$lang->project->treeLevel['root'] = '全部摺疊'; +$lang->project->treeLevel['story'] = '顯示需求'; +$lang->project->treeLevel['task'] = '顯示任務'; +$lang->project->treeLevel['all'] = '全部展開'; global $config; if($config->global->flow == 'onlyTask') diff --git a/module/project/model.php b/module/project/model.php index 62da93a77d..995250acfb 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -17,16 +17,16 @@ class projectModel extends model const LINK_MEMBERS_ONE_TIME = 20; /** - * Check the privilege. - * - * @param object $project + * Check the privilege. + * + * @param object $project * @access public * @return bool */ public function checkPriv($project) { /* If is admin, return true. */ - if($this->app->user->admin) return true; + if($this->app->user->admin) return true; $acls = $this->app->user->rights['acls']; if(!empty($acls['projects']) and !in_array($project->id, $acls['projects'])) return false; @@ -36,7 +36,7 @@ class projectModel extends model /* Get all teams of all projects and group by projects, save it as static. */ static $teams; - if(empty($teams)) $teams = $this->dao->select('project, account')->from(TABLE_TEAM)->fetchGroup('project', 'account'); + if(empty($teams)) $teams = $this->dao->select('root, account')->from(TABLE_TEAM)->where('type')->eq('project')->fetchGroup('root', 'account'); $currentTeam = isset($teams[$project->id]) ? $teams[$project->id] : array(); /* If project is private, only members can access. */ @@ -61,9 +61,9 @@ class projectModel extends model /** * Set menu. - * - * @param array $projects - * @param int $projectID + * + * @param array $projects + * @param int $projectID * @param string $extra * @access public * @return void @@ -74,7 +74,7 @@ class projectModel extends model $project = $this->getById($projectID); /* Unset story, bug, build and testtask if type is ops. */ - if($project and $project->type == 'ops') + if($project and $project->type == 'ops') { unset($this->lang->project->menu->story); unset($this->lang->project->menu->bug); @@ -93,7 +93,7 @@ class projectModel extends model $moduleName = $this->app->getModuleName(); $methodName = $this->app->getMethodName(); - if($this->cookie->projectMode == 'noclosed' and $project->status == 'done') + if($this->cookie->projectMode == 'noclosed' and $project->status == 'done') { setcookie('projectMode', 'all'); $this->cookie->projectMode = 'all'; @@ -108,12 +108,12 @@ class projectModel extends model } /** - * Create the select code of projects. - * - * @param array $projects - * @param int $projectID - * @param string $currentModule - * @param string $currentMethod + * Create the select code of projects. + * + * @param array $projects + * @param int $projectID + * @param string $currentModule + * @param string $currentMethod * @param string $extra * @access public * @return string @@ -133,7 +133,7 @@ class projectModel extends model /** * Get project tree menu. - * + * * @access public * @return void */ @@ -150,7 +150,7 @@ class projectModel extends model $productName = isset($products[$productID]) ? $products[$productID] : $this->lang->project->noProduct; $projectTree .= "
  • $productName
      "; - + foreach($projects as $project) { if($project->status != 'done') @@ -160,9 +160,9 @@ class projectModel extends model } $hasDone = false; - foreach($projects as $project) + foreach($projects as $project) { - if($project->status == 'done') + if($project->status == 'done') { $hasDone = true; break; @@ -191,9 +191,9 @@ class projectModel extends model /** * Save the project id user last visited to session. - * - * @param int $projectID - * @param array $projects + * + * @param int $projectID + * @param array $projects * @access public * @return int */ @@ -217,8 +217,10 @@ class projectModel extends model } /** - * Create a project. - * + * Create a project. + * + * @param string $copyProjectID + * * @access public * @return void */ @@ -232,7 +234,7 @@ class projectModel extends model ->setDefault('team', substr($this->post->name,0, 30)) ->join('whitelist', ',') ->stripTags($this->config->project->editor->create['id'], $this->config->allowedTags) - ->remove('products, workDays, delta, branch,uid') + ->remove('products, workDays, delta, branch, uid, plans') ->get(); $project = $this->loadModel('file')->processImgURL($project, $this->config->project->editor->create['id'], $this->post->uid); $this->dao->insert(TABLE_PROJECT)->data($project) @@ -257,14 +259,15 @@ class projectModel extends model $this->file->updateObjectID($this->post->uid, $projectID, 'project'); /* Copy team of project. */ - if($copyProjectID != '') + if($copyProjectID != '') { - $members = $this->dao->select('*')->from(TABLE_TEAM)->where('project')->eq($copyProjectID)->fetchAll(); + $members = $this->dao->select('*')->from(TABLE_TEAM)->where('root')->eq($copyProjectID)->andWhere('type')->eq('project')->fetchAll(); foreach($members as $member) { - $member->project = $projectID; - $member->join = $today; - $member->days = $project->days; + $member->root = $projectID; + $member->join = $today; + $member->days = $project->days; + $member->type = 'project'; $this->dao->insert(TABLE_TEAM)->data($member)->exec(); if($member->account == $this->app->user->account) $creatorExists = true; } @@ -274,12 +277,13 @@ class projectModel extends model if($copyProjectID == '' or !$creatorExists) { $member = new stdclass(); - $member->project = $projectID; - $member->account = $this->app->user->account; - $member->role = $this->lang->user->roleList[$this->app->user->role]; - $member->join = $today; - $member->days = $project->days; - $member->hours = $this->config->project->defaultWorkhours; + $member->root = $projectID; + $member->account = $this->app->user->account; + $member->role = $this->lang->user->roleList[$this->app->user->role]; + $member->join = $today; + $member->type = 'project'; + $member->days = $project->days; + $member->hours = $this->config->project->defaultWorkhours; $this->dao->insert(TABLE_TEAM)->data($member)->exec(); } @@ -293,13 +297,13 @@ class projectModel extends model $this->dao->insert(TABLE_DOCLIB)->data($lib)->exec(); if(!dao::isError()) $this->loadModel('score')->create('project', 'create', $projectID); return $projectID; - } + } } /** * Update a project. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return array */ @@ -316,7 +320,7 @@ class projectModel extends model ->setDefault('team', $this->post->name) ->join('whitelist', ',') ->stripTags($this->config->project->editor->edit['id'], $this->config->allowedTags) - ->remove('products,branch,uid') + ->remove('products, branch, uid, plans') ->get(); $project = $this->loadModel('file')->processImgURL($project, $this->config->project->editor->edit['id'], $this->post->uid); $this->dao->update(TABLE_PROJECT)->data($project) @@ -336,11 +340,12 @@ class projectModel extends model { if(!empty($value) and !isset($team[$value])) { - $member->project = (int)$projectID; + $member->root = (int)$projectID; $member->account = $value; $member->join = helper::today(); $member->role = $this->lang->project->$fieldName; $member->days = $project->days; + $member->type = 'project'; $member->hours = $this->config->project->defaultWorkhours; $this->dao->replace(TABLE_TEAM)->data($member)->exec(); } @@ -356,8 +361,8 @@ class projectModel extends model } /** - * Batch update. - * + * Batch update. + * * @access public * @return void */ @@ -365,7 +370,7 @@ class projectModel extends model { $projects = array(); $allChanges = array(); - $data = fixer::input('post')->get(); + $data = fixer::input('post')->get(); $oldProjects = $this->getByIdList($this->post->projectIDList); foreach($data->projectIDList as $projectID) { @@ -410,7 +415,8 @@ class projectModel extends model if(!empty($value) and !isset($team[$value])) { $member = new stdClass(); - $member->project = (int)$projectID; + $member->root = (int)$projectID; + $member->type = 'project'; $member->account = $value; $member->join = helper::today(); $member->role = $this->lang->project->$fieldName; @@ -430,8 +436,8 @@ class projectModel extends model /** * Start project. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -453,8 +459,8 @@ class projectModel extends model /** * Put project off. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -474,8 +480,8 @@ class projectModel extends model /** * Suspend project. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -497,8 +503,8 @@ class projectModel extends model /** * Activate project. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -561,8 +567,8 @@ class projectModel extends model /** * Close project. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return array */ @@ -587,8 +593,8 @@ class projectModel extends model /** * Get project pairs. - * - * @param string $mode all|noclosed or empty + * + * @param string $mode all|noclosed or empty * @access public * @return array */ @@ -624,8 +630,8 @@ class projectModel extends model /** * Get by idList. - * - * @param array $projectIDList + * + * @param array $projectIDList * @access public * @return array */ @@ -636,10 +642,10 @@ class projectModel extends model /** * Get project lists. - * + * * @param string $status all|undone|wait|running - * @param int $limit - * @param int $productID + * @param int $limit + * @param int $productID * @access public * @return array */ @@ -677,10 +683,10 @@ class projectModel extends model /** * Get project lists. - * + * * @param string $status involved - * @param int $limit - * @param int $productID + * @param int $limit + * @param int $productID * @param int $branch * @access public * @return array @@ -691,7 +697,7 @@ class projectModel extends model { return $this->dao->select('t2.*')->from(TABLE_PROJECTPRODUCT)->alias('t1') ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->leftJoin(TABLE_TEAM)->alias('t3')->on('t3.project=t2.id') + ->leftJoin(TABLE_TEAM)->alias('t3')->on('t3.root=t2.id') ->where('t1.product')->eq($productID) ->andWhere('t2.deleted')->eq(0) ->andWhere('t2.iscat')->eq(0) @@ -699,6 +705,7 @@ class projectModel extends model ->andWhere('t2.openedBy', true)->eq($this->app->user->account) ->orWhere('t3.account')->eq($this->app->user->account) ->markRight(1) + ->andWhere('t3.type')->eq('project') ->orderBy('order_desc') ->beginIF($limit)->limit($limit)->fi() ->fetchAll('id'); @@ -706,12 +713,13 @@ class projectModel extends model else { return $this->dao->select('t1.*, IF(INSTR(" done", t1.status) < 2, 0, 1) AS isDone')->from(TABLE_PROJECT)->alias('t1') - ->leftJoin(TABLE_TEAM)->alias('t2')->on('t2.project=t1.id') + ->leftJoin(TABLE_TEAM)->alias('t2')->on('t2.root=t1.id') ->where('t1.iscat')->eq(0) ->andWhere('t1.openedBy', true)->eq($this->app->user->account) ->orWhere('t2.account')->eq($this->app->user->account) ->markRight(1) ->andWhere('t1.deleted')->eq(0) + ->andWhere('t2.type')->eq('project') ->orderBy('t1.order_desc') ->beginIF($limit)->limit($limit)->fi() ->fetchAll('id'); @@ -720,7 +728,7 @@ class projectModel extends model /** * Get projects lists grouped by product. - * + * * @access public * @return array */ @@ -738,14 +746,14 @@ class projectModel extends model { foreach($product as $ID => $project) { - if(!$this->checkPriv($projects[$project->id])) + if(!$this->checkPriv($projects[$project->id])) { unset($list[$id][$ID]); } if(!$project->product) { if($this->checkPriv($projects[$project->id])) $noProducts[] = $project; - unset($list[$id][$ID]); + unset($list[$id][$ID]); } } } @@ -757,12 +765,12 @@ class projectModel extends model /** * Get project stats. - * - * @param string $status - * @param int $productID - * @param int $itemCounts - * @param string $orderBy - * @param int $pager + * + * @param string $status + * @param int $productID + * @param int $itemCounts + * @param string $orderBy + * @param int $pager * @access public * @return void */ @@ -949,8 +957,8 @@ class projectModel extends model /** * Get project by id. - * - * @param int $projectID + * + * @param int $projectID * @param bool $setImgSize * @access public * @return void @@ -970,8 +978,8 @@ class projectModel extends model } $total = $this->dao->select(' - SUM(estimate) AS totalEstimate, - SUM(consumed) AS totalConsumed, + SUM(estimate) AS totalEstimate, + SUM(consumed) AS totalConsumed, SUM(`left`) AS totalLeft') ->from(TABLE_TASK) ->where('project')->eq((int)$projectID) @@ -980,7 +988,7 @@ class projectModel extends model ->andWhere('parent')->eq(0) ->fetch(); $project->days = $project->days ? $project->days : ''; - $project->totalHours = $this->dao->select('sum(days * hours) AS totalHours')->from(TABLE_TEAM)->where('project')->eq($project->id)->fetch('totalHours'); + $project->totalHours = $this->dao->select('sum(days * hours) AS totalHours')->from(TABLE_TEAM)->where('root')->eq($project->id)->andWhere('type')->eq('project')->fetch('totalHours'); $project->totalEstimate = round($total->totalEstimate, 1); $project->totalConsumed = round($total->totalConsumed, 1); $project->totalLeft = round($total->totalLeft, 1); @@ -992,9 +1000,9 @@ class projectModel extends model } /** - * Get the default managers for a project from it's related products. - * - * @param int $projectID + * Get the default managers for a project from it's related products. + * + * @param int $projectID * @access public * @return object */ @@ -1015,8 +1023,8 @@ class projectModel extends model /** * Get products of a project. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return array */ @@ -1029,7 +1037,7 @@ class projectModel extends model if(!$withBranch) return $this->loadModel('tutorial')->getProductPairs(); return $this->loadModel('tutorial')->getProjectProducts(); } - $query = $this->dao->select('t2.id, t2.name, t2.type, t1.branch')->from(TABLE_PROJECTPRODUCT)->alias('t1') + $query = $this->dao->select('t2.id, t2.name, t2.type, t1.branch, t1.plan')->from(TABLE_PROJECTPRODUCT)->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2') ->on('t1.product = t2.id') ->where('t1.project')->eq((int)$projectID); @@ -1039,12 +1047,12 @@ class projectModel extends model /** * Build story search form. - * - * @param array $products - * @param array $branchGroups - * @param array $modules - * @param int $queryID - * @param string $actionURL + * + * @param array $products + * @param array $branchGroups + * @param array $modules + * @param int $queryID + * @param string $actionURL * @param string $type * @access public * @return void @@ -1103,9 +1111,9 @@ class projectModel extends model } /** - * Get projects to import + * Get projects to import * - * @param array $projectIds + * @param array $projectIds * @access public * @return array */ @@ -1128,8 +1136,8 @@ class projectModel extends model /** * Update products of a project. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -1140,6 +1148,7 @@ class projectModel extends model if(!isset($_POST['products'])) return; $products = $_POST['products']; $branches = isset($_POST['branch']) ? $_POST['branch'] : array(); + $plans = $_POST['plans']; $existedProducts = array(); $addedProducts = array(); @@ -1160,15 +1169,16 @@ class projectModel extends model $data->project = $projectID; $data->product = $productID; $data->branch = isset($branches[$i]) ? $branches[$i] : 0; + $data->plan = isset($plans[$productID]) ? $plans[$productID] : 0; $this->dao->insert(TABLE_PROJECTPRODUCT)->data($data)->exec(); $existedProducts[$productID] = true; } } /** - * Get related projects - * - * @param int $projectID + * Get related projects + * + * @param int $projectID * @access public * @return array */ @@ -1190,9 +1200,9 @@ class projectModel extends model /** * Get tasks can be imported. - * + * * @param int $toProject - * @param array $branches + * @param array $branches * @access public * @return array */ @@ -1209,6 +1219,7 @@ class projectModel extends model ->leftJoin(TABLE_USER)->alias('t3')->on('t1.assignedTo = t3.account') ->where('t1.status')->in('wait, doing, pause, cancel') ->andWhere('t1.deleted')->eq(0) + ->andWhere('t1.parent')->eq(0) ->andWhere('t1.project')->in(array_keys($projects)) ->andWhere("(t1.story = 0 OR (t2.branch in ('0','" . join("','", $branches) . "') and t2.product " . helper::dbIN(array_keys($branches)) . "))") ->fetchGroup('project', 'id'); @@ -1217,8 +1228,8 @@ class projectModel extends model /** * Import tasks. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -1231,20 +1242,20 @@ class projectModel extends model foreach($tasks as $task) { /* Save the assignedToes and stories, should linked to project. */ - $assignedToes[$task->assignedTo] = $task->project; - $stories[$task->story] = $task->story; + $assignedToes[$task->assignedTo] = $task->project; + $stories[$task->story] = $task->story; $data = new stdclass(); $data->project = $projectID; if($task->status == 'cancel') { - $data->canceledBy = ''; - $data->canceledDate = NULL; + $data->canceledBy = ''; + $data->canceledDate = null; } - $data->status = $task->consumed > 0 ? 'doing' : 'wait'; - $this->dao->update(TABLE_TASK)->data($data)->where('id')->in($this->post->tasks)->exec(); + $data->status = $task->consumed > 0 ? 'doing' : 'wait'; + $this->dao->update(TABLE_TASK)->data($data)->where('id')->in($this->post->tasks)->orWhere('parent')->in($this->post->tasks)->exec(); $this->loadModel('action')->create('task', $task->id, 'moved', '', $task->project); } @@ -1257,9 +1268,14 @@ class projectModel extends model { if(!isset($teamMembers[$account])) { - $role = $this->dao->select('*')->from(TABLE_TEAM)->where('project')->eq($preProjectID)->andWhere('account')->eq($account)->fetch(); - $role->project = $projectID; - $role->join = helper::today(); + $role = $this->dao->select('*')->from(TABLE_TEAM) + ->where('root')->eq($preProjectID) + ->andWhere('account')->eq($account) + ->andWhere('type')->eq('project') + ->fetch(); + + $role->root = $projectID; + $role->join = helper::today(); $this->dao->insert(TABLE_TEAM)->data($role)->exec(); } } @@ -1279,9 +1295,9 @@ class projectModel extends model } /** - * Import task from Bug. - * - * @param int $projectID + * Import task from Bug. + * + * @param int $projectID * @access public * @return void */ @@ -1326,7 +1342,7 @@ class projectModel extends model if(!$bug->confirmed) $this->dao->update(TABLE_BUG)->set('confirmed')->eq(1)->where('id')->eq($bug->id)->exec(); $this->dao->insert(TABLE_TASK)->data($task)->checkIF($bugToTasks->estimate[$key] != '', 'estimate', 'float')->exec(); - if(dao::isError()) + if(dao::isError()) { echo js::error(dao::getError()); die(js::reload('parent')); @@ -1387,8 +1403,8 @@ class projectModel extends model /** * Get child projects. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -1399,8 +1415,8 @@ class projectModel extends model /** * Update childs. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -1419,22 +1435,29 @@ class projectModel extends model /** * Link story. - * - * @param int $projectID + * + * @param int $projectID + * @param array $stories + * @param array $products + * * @access public - * @return void + * @return mixed */ - public function linkStory($projectID, $stories = array()) + public function linkStory($projectID, $stories = array(), $products = array()) { if(empty($stories)) $stories = $this->post->stories; if(empty($stories)) return false; + if(empty($products)) $products = $this->post->products; $this->loadModel('action'); - $versions = $this->loadModel('story')->getVersions($stories); - $lastOrder = (int)$this->dao->select('*')->from(TABLE_PROJECTSTORY)->where('project')->eq($projectID)->orderBy('order_desc')->limit(1)->fetch('order'); + $versions = $this->loadModel('story')->getVersions($stories); + $linkedStories = $this->dao->select('*')->from(TABLE_PROJECTSTORY)->where('project')->eq($projectID)->orderBy('order_desc')->fetchPairs('story', 'order'); + $lastOrder = reset($linkedStories); foreach($stories as $key => $storyID) { - $productID = (int)$this->post->products[$storyID]; + if(isset($linkedStories[$storyID])) continue; + + $productID = (int)$products[$storyID]; $data = new stdclass(); $data->project = $projectID; $data->product = $productID; @@ -1444,14 +1467,42 @@ class projectModel extends model $this->dao->insert(TABLE_PROJECTSTORY)->data($data)->exec(); $this->story->setStage($storyID); $this->action->create('story', $storyID, 'linked2project', '', $projectID); - } + } } /** - * Unlink story. - * - * @param int $projectID - * @param int $storyID + * Link all stories by project. + * + * @param $projectID + */ + public function linkStories($projectID) + { + $plans = $this->dao->select('plan,product')->from(TABLE_PROJECTPRODUCT) + ->where('project')->eq($projectID) + ->fetchPairs('plan', 'product'); + + $planStories = array(); + $planProducts = array(); + if(!empty($plans)) + { + foreach($plans as $planID => $productID) + { + $planStory = $this->loadModel('story')->getPlanStories($planID, 'active'); + if(!empty($planStory)) + { + $planStories = array_merge($planStories, array_keys($planStory)); + foreach($planStory as $story) $planProducts[$story->id] = $story->product; + } + } + } + $this->linkStory($projectID, $planStories, $planProducts); + } + + /** + * Unlink story. + * + * @param int $projectID + * @param int $storyID * @access public * @return void */ @@ -1481,9 +1532,9 @@ class projectModel extends model } /** - * Get team members. - * - * @param int $projectID + * Get team members. + * + * @param int $projectID * @access public * @return array */ @@ -1492,15 +1543,16 @@ class projectModel extends model if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getTeamMembers(); return $this->dao->select("t1.*, t1.hours * t1.days AS totalHours, if(t2.deleted='0', t2.realname, t1.account) as realname")->from(TABLE_TEAM)->alias('t1') ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account') - ->where('t1.project')->eq((int)$projectID) + ->where('t1.root')->eq((int)$projectID) + ->andWhere('t1.type')->eq('project') ->fetchAll('account'); } /** * Get team members in pair. - * - * @param int $projectID - * @param string $params + * + * @param int $projectID + * @param string $params * @access public * @return array */ @@ -1509,7 +1561,8 @@ class projectModel extends model if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getTeamMembersPairs(); $users = $this->dao->select('t1.account, t2.realname')->from(TABLE_TEAM)->alias('t1') ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account') - ->where('t1.project')->eq((int)$projectID) + ->where('t1.root')->eq((int)$projectID) + ->andWhere('t1.type')->eq('project') ->beginIF($params == 'nodeleted' or empty($this->config->user->showDeleted)) ->andWhere('t2.deleted')->eq(0) ->fi() @@ -1525,29 +1578,30 @@ class projectModel extends model /** * Get teams which can be imported. - * - * @param string $account - * @param int $currentProject + * + * @param string $account + * @param int $currentProject * @access public * @return array */ public function getTeams2Import($account, $currentProject) { - return $this->dao->select('t1.project, t2.name as projectName') + return $this->dao->select('t1.root, t2.name as projectName') ->from(TABLE_TEAM)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.root = t2.id') ->where('t1.account')->eq($account) - ->andWhere('t1.project')->ne($currentProject) - ->groupBy('t1.project') - ->orderBy('t1.project DESC') + ->andWhere('t1.root')->ne($currentProject) + ->andWhere('t1.type')->eq('project') + ->groupBy('t1.root') + ->orderBy('t1.root DESC') ->fetchPairs(); } /** * Get members of a project who can be imported. - * - * @param int $project - * @param array $currentMembers + * + * @param int $project + * @param array $currentMembers * @access public * @return array */ @@ -1557,8 +1611,9 @@ class projectModel extends model return $this->dao->select('account, role, hours') ->from(TABLE_TEAM) - ->where('project')->eq($project) + ->where('root')->eq($project) ->andWhere('account')->notIN($currentMembers) + ->andWhere('type')->eq('project') ->fetchAll('account'); } @@ -1590,15 +1645,17 @@ class projectModel extends model { $this->dao->update(TABLE_TEAM) ->data($member) - ->where('project')->eq((int)$projectID) + ->where('root')->eq((int)$projectID) ->andWhere('account')->eq($account) + ->andWhere('type')->eq('project') ->exec(); } else { - $member->project = (int)$projectID; + $member->root = (int)$projectID; $member->account = $account; $member->join = helper::today(); + $member->type = 'project'; $this->dao->insert(TABLE_TEAM)->data($member)->exec(); } } @@ -1606,20 +1663,20 @@ class projectModel extends model /** * Unlink a member. - * - * @param int $projectID - * @param string $account + * + * @param int $projectID + * @param string $account * @access public * @return void */ public function unlinkMember($projectID, $account) { - $this->dao->delete()->from(TABLE_TEAM)->where('project')->eq((int)$projectID)->andWhere('account')->eq($account)->exec(); + $this->dao->delete()->from(TABLE_TEAM)->where('root')->eq((int)$projectID)->andWhere('account')->eq($account)->andWhere('type')->eq('project')->exec(); } /** * Compute burn of a project. - * + * * @access public * @return array */ @@ -1654,8 +1711,8 @@ class projectModel extends model /** * Fix burn for first day. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return void */ @@ -1678,9 +1735,9 @@ class projectModel extends model } /** - * Get burn data for flot - * - * @param int $projectID + * Get burn data for flot + * + * @param int $projectID * @access public * @return array */ @@ -1694,7 +1751,7 @@ class projectModel extends model $count = 0; $burnData = array(); - foreach($sets as $date => $set) + foreach($sets as $date => $set) { if($date < $project->begin) continue; if($date > $project->end) continue; @@ -1709,12 +1766,12 @@ class projectModel extends model /** * Process burndown datas when the sets is smaller than the itemCounts. - * - * @param array $sets - * @param int $itemCounts - * @param date $begin - * @param date $end - * @param string $mode + * + * @param array $sets + * @param int $itemCounts + * @param date $begin + * @param date $end + * @param string $mode * @access public * @return array */ @@ -1772,10 +1829,10 @@ class projectModel extends model /** * Get taskes by search. - * - * @param string $condition - * @param object $pager - * @param string $orderBy + * + * @param string $condition + * @param object $pager + * @param string $orderBy * @access public * @return array */ @@ -1802,13 +1859,13 @@ class projectModel extends model } /** - * Get bugs by search in project. - * - * @param int $products - * @param int $projectID - * @param int $sql - * @param int $pager - * @param int $orderBy + * Get bugs by search in project. + * + * @param int $products + * @param int $projectID + * @param int $sql + * @param int $pager + * @param int $orderBy * @access public * @return void */ @@ -1829,8 +1886,8 @@ class projectModel extends model /** * Get the summary of project. - * - * @param array $tasks + * + * @param array $tasks * @access public * @return string */ @@ -1846,7 +1903,8 @@ class projectModel extends model $totalLeft += (($task->status == 'cancel' or $task->closedReason == 'cancel') ? 0 : $task->left); $statusVar = 'status' . ucfirst($task->status); $$statusVar ++; - if(!empty($task->children)){ + if(!empty($task->children)) + { $taskSum += count($task->children); foreach($task->children as $child) { @@ -1861,9 +1919,9 @@ class projectModel extends model /** * Judge an action is clickable or not. - * + * * @param object $project - * @param string $action + * @param string $action * @access public * @return bool */ @@ -1882,10 +1940,10 @@ class projectModel extends model /** * Create the link from module,method,extra - * - * @param string $module - * @param string $method - * @param mix $extra + * + * @param string $module + * @param string $method + * @param mix $extra * @access public * @return void */ @@ -1896,12 +1954,12 @@ class projectModel extends model { $module = 'project'; $method = 'task'; - } + } if($module == 'build' and ($method == 'edit' || $method= 'view')) - { + { $module = 'project'; $method = 'build'; - } + } if($module == 'project' and $method == 'create') return; if($extra != '') @@ -1922,12 +1980,12 @@ class projectModel extends model } /** - * Get no weekend date - * - * @param string $begin - * @param string $end - * @param string $type - * @param string|int $interval + * Get no weekend date + * + * @param string $begin + * @param string $end + * @param string $type + * @param string|int $interval * @param string $format * @access public * @return array @@ -1977,8 +2035,8 @@ class projectModel extends model /** * Get total estimate. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return float */ @@ -2001,7 +2059,7 @@ class projectModel extends model if($this->app->user->admin) return true; /* Get all teams of all projects and group by projects, save it as static. */ - $projects = $this->dao->select('project, limited')->from(TABLE_TEAM)->where('account')->eq($this->app->user->account)->andWhere('limited')->eq('yes')->orderBy('project asc')->fetchPairs('project', 'project'); + $projects = $this->dao->select('root, limited')->from(TABLE_TEAM)->where('account')->eq($this->app->user->account)->andWhere('limited')->eq('yes')->andWhere('type')->eq('project')->orderBy('root asc')->fetchPairs('root', 'root'); $_SESSION['limitedProjects'] = join(',', $projects); } @@ -2027,8 +2085,8 @@ class projectModel extends model /** * Get branches of project. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return array */ @@ -2145,11 +2203,11 @@ class projectModel extends model } /** - * Get Kanban tasks - * - * @param int $projectID - * @param string $orderBy - * @param object $pager + * Get Kanban tasks + * + * @param int $projectID + * @param string $orderBy + * @param object $pager * @access public * @return void */ @@ -2172,10 +2230,10 @@ class projectModel extends model } /** - * Get kanban group data. - * - * @param array $tasks - * @param array $bugs + * Get kanban group data. + * + * @param array $tasks + * @param array $bugs * @access public * @return array */ @@ -2226,9 +2284,9 @@ class projectModel extends model /** * Save Kanban Data. - * - * @param int $projectID - * @param array $kanbanDatas + * + * @param int $projectID + * @param array $kanbanDatas * @access public * @return void */ @@ -2242,8 +2300,8 @@ class projectModel extends model /** * Get Prev Kanban. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return array */ @@ -2255,8 +2313,8 @@ class projectModel extends model /** * Get kanban setting. - * - * @param int $projectID + * + * @param int $projectID * @access public * @return object */ @@ -2281,10 +2339,10 @@ class projectModel extends model /** * Build burn data. - * - * @param int $projectID - * @param array $dateList - * @param string $type + * + * @param int $projectID + * @param array $dateList + * @param string $type * @access public * @return array */ @@ -2448,9 +2506,9 @@ class projectModel extends model /** * Format tasks for tree. - * - * @param array $tasks - * @param object $story + * + * @param array $tasks + * @param object $story * @access public * @return array */ @@ -2525,4 +2583,25 @@ class projectModel extends model if(isset($fullTrees[0]) and empty($fullTrees[0]->children)) array_shift($fullTrees); return array_values($fullTrees); } + + /** + * Get plans by $productID. + * + * @param int|array $productID + * + * @return mixed + */ + public function getPlans($productID) + { + $plans = $this->dao->select('id,title,product')->from(TABLE_PRODUCTPLAN) + ->where('product')->in($productID) + ->fetchAll(); + + $productPlans = array(); + foreach ($plans as $plan) + { + $productPlans[$plan->product][$plan->id] = $plan->title; + } + return $productPlans; + } } diff --git a/module/project/view/build.html.php b/module/project/view/build.html.php index bca38a49d5..100e960191 100644 --- a/module/project/view/build.html.php +++ b/module/project/view/build.html.php @@ -13,60 +13,65 @@ build->confirmDelete)?> -
      -
      - icons['build']);?> project->build;?> +
      +
      + +
      +
  • productplan->product;?> name;?>
    product->branch;?> branch, 'class="form-control"');?>
    productplan->title;?> title, "class='form-control' autocomplete='off'");?>
    productplan->begin;?> begin, "class='form-control form-date'");?>
    productplan->end;?>end, 'class="form-control form-date"');?> + end == '2030-01-01' ? ' disabled="disabled"' : '';?> + end : '', 'class="form-control form-date"' . $disabled);?> +     productplan->endList , '', "onclick='computeEndDate(this.value)'");?>
    productplan->desc;?> desc), "rows='10' class='form-control'");?>
    - id); diff --git a/module/productplan/view/view.html.php b/module/productplan/view/view.html.php index 59422c92de..df56628229 100644 --- a/module/productplan/view/view.html.php +++ b/module/productplan/view/view.html.php @@ -92,9 +92,7 @@ productplan->updateOrder);?> priAB);?> story->module);?> story->title);?> openedByAB);?> assignedToAB);?>
    - - id));?> story->priList, $story->pri, $story->pri)?>'>story->priList, $story->pri, $story->pri);?>module)) echo $modulePairs[$story->module];?>module, '');?> title);?> openedBy);?> assignedTo);?>
    - - createLink('bug', 'view', "bugID=$bug->id"), sprintf("%03d", $bug->id));?> bug->priList, $bug->pri, $bug->pri)?>'>bug->priList, $bug->pri, $bug->pri);?>productplan->title;?> title;?>
    product->branch;?>branch];?>
    product->branch;?>branch];?>
    productplan->begin;?> begin;?>
    productplan->end;?>end;?>end == '2030-01-01' ? $lang->productplan->future : $plan->end;?>
    productplan->desc;?>
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    build->id;?>build->product;?>build->name;?>build->scmPath;?>build->filePath;?>build->date;?>build->builder;?>actions;?>
    id;?>productName;?> + branchName) echo "{$build->branchName}"?> + createLink('build', 'view', "build=$build->id"), $build->name);?> + scmPath, 'http') === 0 ? html::a($build->scmPath) : $build->scmPath;?>filePath, 'http') === 0 ? html::a($build->filePath) : $build->filePath;?>date?>builder]?> + createLink('build', 'view', "buildID=$build->id&type=story&link=true"), "", '', "class='btn' title='{$lang->build->linkStory}'"); + } + common::printIcon('testtask', 'create', "product=$build->product&project=$project->id&build=$build->id", $build, 'list', 'bullhorn'); + $lang->project->bug = $lang->project->viewBug; + common::printIcon('project', 'bug', "project=$project->id&orderBy=status&build=$build->id", $build, 'list'); + common::printIcon('build', 'edit', "buildID=$build->id", $build, 'list'); + if(common::hasPriv('build', 'delete', $build)) + { + $deleteURL = $this->createLink('build', 'delete', "buildID=$build->id&confirm=yes"); + echo html::a("javascript:ajaxDelete(\"$deleteURL\",\"buildList\",confirmDelete)", '', '', "class='btn' title='{$lang->build->delete}'"); + } + ?> +
    + -
    - id");?> -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    build->id;?>build->product;?>build->name;?>build->scmPath;?>build->filePath;?>build->date;?>build->builder;?>actions;?>
    id;?>productName;?> - branchName) echo "{$build->branchName}"?> - createLink('build', 'view', "build=$build->id"), $build->name);?> - scmPath, 'http') === 0 ? html::a($build->scmPath) : $build->scmPath;?>filePath, 'http') === 0 ? html::a($build->filePath) : $build->filePath;?>date?>builder]?> - createLink('build', 'view', "buildID=$build->id&type=story&link=true"), "", '', "class='btn-icon' title='{$lang->build->linkStory}'"); - } - common::printIcon('testtask', 'create', "product=$build->product&project=$project->id&build=$build->id", $build, 'list', 'bullhorn'); - $lang->project->bug = $lang->project->viewBug; - common::printIcon('project', 'bug', "project=$project->id&orderBy=status&build=$build->id", $build, 'list'); - common::printIcon('build', 'edit', "buildID=$build->id", $build, 'list'); - if(common::hasPriv('build', 'delete', $build)) - { - $deleteURL = $this->createLink('build', 'delete', "buildID=$build->id&confirm=yes"); - echo html::a("javascript:ajaxDelete(\"$deleteURL\",\"buildList\",confirmDelete)", '', '', "class='btn-icon' title='{$lang->build->delete}'"); - } - ?> -
    + diff --git a/module/project/view/burn.html.php b/module/project/view/burn.html.php index 2cb4e85d64..6d1c6d5df2 100644 --- a/module/project/view/burn.html.php +++ b/module/project/view/burn.html.php @@ -27,7 +27,7 @@ $weekend = ($type == 'noweekend') ? 'withweekend' : "noweekend"; common::printLink('project', 'computeBurn', 'reload=yes', $lang->project->computeBurn, 'hiddenwin', "title='{$lang->project->computeBurn}{$lang->project->burn}' class='btn btn-primary btn-sm' id='computeBurn'"); echo html::a($this->createLink('project', 'burn', "projectID=$projectID&type=$weekend&interval=$interval"), $lang->project->$weekend, '', "class='btn btn-sm'"); - common::printLink('project', 'fixFirst', "project=$project->id", $lang->project->fixFirst, '', "class='btn btn-sm iframe' data-width='500'"); + common::printLink('project', 'fixFirst', "project=$project->id", $lang->project->fixFirst, '', "class='btn btn-sm iframe' data-width='600'"); echo $lang->project->howToUpdateBurn; ?> diff --git a/module/project/view/create.html.php b/module/project/view/create.html.php index db40c91339..0b823d15e1 100644 --- a/module/project/view/create.html.php +++ b/module/project/view/create.html.php @@ -44,22 +44,22 @@ - +
    - + - + - + - + + config->global->flow == 'onlyTask') echo "class='hidden'";?>> + + + - + - + > diff --git a/module/project/view/edit.html.php b/module/project/view/edit.html.php index 85f467c348..220cdaa3ca 100644 --- a/module/project/view/edit.html.php +++ b/module/project/view/edit.html.php @@ -23,11 +23,11 @@ -
    project->name;?>project->name;?>
    project->code;?>
    project->dateRange;?>
    - project->begin . "'");?> + begin) ? $plan->begin : date('Y-m-d')), "class='form-control w-100px form-date' onchange='computeWorkDays()' placeholder='" . $lang->project->begin . "'");?> project->to;?> - project->end . "'");?> + end) ? $plan->end : ''), "class='form-control form-date' onchange='computeWorkDays()' placeholder='" . $lang->project->end . "'");?>
    @@ -70,15 +70,15 @@ project->days;?>
    - + begin) ? helper::workDays($plan->begin, $plan->end) : ''), "class='form-control' autocomplete='off'");?> project->day;?>
    project->teamname;?>
    project->type;?> @@ -96,8 +96,8 @@
    - id, "class='form-control chosen' onchange='loadBranches(this)'");?> - + id, "class='form-control chosen' onchange='loadBranches(this)' data-last='" . $product->id . "'");?> + type != 'normal') echo html::select("branch[$i]", $branchGroups[$product->id], $product->branch, "class='form-control' style='width:80px'")?>
    @@ -106,20 +106,32 @@
    - +
    project->linkPlan;?> +
    + begin)):?> +
    + product . "]", $productPlan, $plan->id, "class='form-control'");?> +
    + +
    +
    project->desc;?>
    project->acl;?> project->aclList, $acl, "onclick='setWhite(this.value);'", 'block'));?>
    project->whitelist;?>
    +
    - + @@ -58,15 +58,15 @@ project->day;?> - + - + - + @@ -115,7 +115,7 @@
    - id, "class='form-control chosen' onchange='loadBranches(this)'");?> + id, "class='form-control chosen' onchange='loadBranches(this)' data-last='" . $product->id . "'");?> type != 'normal' and isset($branchGroups[$product->id])) echo html::select("branch[$i]", $branchGroups[$product->id], $product->branch, "class='form-control' style='width:80px'")?>
    @@ -131,6 +131,18 @@
    + config->global->flow == 'onlyTask') echo "class='hidden'";?>> + + + diff --git a/module/project/view/fixfirst.html.php b/module/project/view/fixfirst.html.php index d31f4c4cde..ddf3f03e3b 100644 --- a/module/project/view/fixfirst.html.php +++ b/module/project/view/fixfirst.html.php @@ -21,7 +21,7 @@ -
    project->totalEstimate . $project->totalEstimate . $lang->project->workHour;?>
    +
    project->totalEstimate . ' : ' . $project->totalEstimate . $lang->project->workHour;?>
    project->name;?> name, "class='form-control' autocomplete='off'");?>
    project->code;?> code, "class='form-control' autocomplete='off'");?>
    project->type;?> project->typeList, $project->type, "class='form-control'");?>
    project->teamname;?> team, "class='form-control' autocomplete='off'");?>
    project->status;?> project->statusList, $project->status, "class='form-control'");?>
    project->linkPlan;?> +
    + $plan):?> +
    + plan, "class='form-control'");?> +
    + +
    +
    project->desc;?> desc), "rows='6' class='form-control'");?>
    diff --git a/module/project/view/grouptask.html.php b/module/project/view/grouptask.html.php index 699f4a1b63..2233c58111 100644 --- a/module/project/view/grouptask.html.php +++ b/module/project/view/grouptask.html.php @@ -25,21 +25,21 @@ - - + - + @@ -55,7 +55,7 @@ $groupWait = 0; $groupDone = 0; $groupDoing = 0; - $groupClosed = 0; + $groupClosed = 0; $groupEstimate = 0.0; $groupConsumed = 0.0; $groupLeft = 0.0; @@ -113,7 +113,7 @@ - + - + task->printCell($field, $task, $users, $browseType, $branchGroups, $modulePairs, $useDatatable ? 'datatable' : 'table');?> children)):?> diff --git a/module/project/view/taskheader.html.php b/module/project/view/taskheader.html.php index e6590fc19e..766a2fa3a7 100644 --- a/module/project/view/taskheader.html.php +++ b/module/project/view/taskheader.html.php @@ -98,7 +98,7 @@ diff --git a/module/project/view/testtask.html.php b/module/project/view/testtask.html.php index d565654f6e..4f8f1342a8 100644 --- a/module/project/view/testtask.html.php +++ b/module/project/view/testtask.html.php @@ -13,57 +13,91 @@ testtask->confirmDelete)?> -
    -
    - icons['test']);?> testtask->browse;?> -
    -
    - -
    -
    +
    +
    + +
    +
    +
    + " . $lang->task->$groupBy, '', "class='expandAll' data-action='expand'")?> " . $lang->task->$groupBy, '', "class='collapseAll hidden' data-action='collapse'")?> task->id;?> priAB;?> task->name;?>task->status;?>task->status;?> task->deadlineAB;?> task->assignedTo;?> task->finishedBy;?> task->estimateAB;?> task->consumedAB;?> task->leftAB;?>task->progress;?>task->progress;?> typeAB;?> actions;?>
    id;?>task->priList), $task->pri, $task->pri)?>'>task->priList), $task->pri, $task->pri);?>task->priList, $task->pri, $task->pri)?>'>task->priList, $task->pri, $task->pri);?> team)) echo '' . $lang->task->multipleAB . ' '; diff --git a/module/project/view/story.html.php b/module/project/view/story.html.php index 156627e13f..7b775d56c6 100644 --- a/module/project/view/story.html.php +++ b/module/project/view/story.html.php @@ -10,9 +10,10 @@ * @link http://www.zentao.net */ ?> + - + @@ -24,7 +25,7 @@
    - lang->story->create = $this->lang->project->createStory; @@ -51,7 +52,18 @@ } else { + echo "
    "; common::printIcon('project', 'linkStory', "project=$project->id", '', 'button', 'link', '', 'link-story-btn'); + if(common::hasPriv('project', 'importPlanStories')) + { + echo "'; + echo "'; + } + echo '
    '; } ?>
    @@ -73,7 +85,6 @@
    - @@ -109,7 +120,7 @@ @@ -233,6 +244,23 @@
    - + id));?>
    + + product->checkedSummary);?> id);?> diff --git a/module/project/view/task.html.php b/module/project/view/task.html.php index 8a7efdad3f..38cab6a3f1 100644 --- a/module/project/view/task.html.php +++ b/module/project/view/task.html.php @@ -76,7 +76,7 @@ js::set('browseType', $browseType);
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    + + idAB;?> +
    testtask->product;?>testtask->name;?>testtask->build;?>testtask->owner;?>testtask->begin;?>testtask->end;?>statusAB;?>actions;?>
    +
    + + + id);?> +
    +
    product, '');?>createLink('testtask', 'view', "taskID=$task->id"), $task->name);?>build == 'trunk' || empty($task->buildName)) ? $lang->trunk : html::a($this->createLink('build', 'view', "buildID=$task->build"), $task->buildName);?>owner];?>begin?>end?>testtask->statusList[$task->status];?> + id", $task, 'list', 'sitemap'); + common::printIcon('testtask', 'linkCase', "taskID=$task->id", $task, 'list', 'link'); + common::printIcon('testtask', 'edit', "taskID=$task->id", $task, 'list'); + common::printIcon('testreport', 'browse', "objectID=$task->product&objectType=product&extra=$task->id", $task, 'list','flag'); - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    idAB;?>testtask->name;?>testtask->build;?>testtask->owner;?>testtask->begin;?>testtask->end;?>statusAB;?>actions;?>
    createLink('testtask', 'view', "taskID=$task->id"), sprintf('%03d', $task->id));?>createLink('testtask', 'view', "taskID=$task->id"), $task->name);?>build == 'trunk' ? print($lang->trunk) : print(html::a($this->createLink('build', 'view', "buildID=$task->build"), $task->buildName));?>owner];?>begin?>end?>testtask->statusList[$task->status];?> - id", $task, 'list', 'sitemap'); - common::printIcon('testtask', 'linkCase', "taskID=$task->id", $task, 'list', 'link'); - common::printIcon('testtask', 'edit', "taskID=$task->id", $task, 'list'); - common::printIcon('testreport', 'create', "objectID=$task->id&objectType=testtask", $task, 'list','flag'); - - if(common::hasPriv('testtask', 'delete', $task)) - { - $deleteURL = $this->createLink('testtask', 'delete', "taskID=$task->id&confirm=yes"); - echo html::a("javascript:ajaxDelete(\"$deleteURL\",\"taskList\",confirmDelete)", '', '', "class='btn-icon' title='{$lang->testtask->delete}'"); - } - ?> -
    + if(common::hasPriv('testtask', 'delete', $task)) + { + $deleteURL = $this->createLink('testtask', 'delete', "taskID=$task->id&confirm=yes"); + echo html::a("javascript:ajaxDelete(\"$deleteURL\",\"taskList\",confirmDelete)", '', '', "class='btn' title='{$lang->testtask->delete}'"); + } + ?> +
    + + + + + + + diff --git a/module/project/view/view.html.php b/module/project/view/view.html.php index 8fb16ea929..bf9b78efa8 100644 --- a/module/project/view/view.html.php +++ b/module/project/view/view.html.php @@ -74,7 +74,7 @@ project->basicInfo?> - + diff --git a/module/release/config.php b/module/release/config.php index 7e52377cd7..464702d309 100644 --- a/module/release/config.php +++ b/module/release/config.php @@ -3,7 +3,7 @@ $config->release = new stdclass(); $config->release->create = new stdclass(); $config->release->edit = new stdclass(); $config->release->create->requiredFields = 'name,date'; -$config->release->edit->requiredFields = 'name,date'; +$config->release->edit->requiredFields = 'name,date,build'; $config->release->editor = new stdclass(); $config->release->editor->create = array('id' => 'desc', 'tools' => 'simpleTools'); diff --git a/module/release/lang/en.php b/module/release/lang/en.php index 71d06752f7..bd330b0bb4 100644 --- a/module/release/lang/en.php +++ b/module/release/lang/en.php @@ -16,11 +16,11 @@ $lang->release->linkStory = "Link Story"; $lang->release->linkBug = "Link Bug"; $lang->release->delete = "Delete"; $lang->release->deleted = 'Deleted'; -$lang->release->view = "Info"; -$lang->release->browse = "Releases"; +$lang->release->view = "Overview"; +$lang->release->browse = "Browse"; $lang->release->changeStatus = "Change Status"; $lang->release->batchUnlink = "Batch Unlink"; -$lang->release->batchUnlinkStory = "Batch Unlink"; +$lang->release->batchUnlinkStory = "Batch Unlink Story"; $lang->release->batchUnlinkBug = "Batch Unlink"; $lang->release->confirmDelete = "Do you want to delete this Release?"; diff --git a/module/release/model.php b/module/release/model.php index ef6b28cd13..b9e5f341e4 100644 --- a/module/release/model.php +++ b/module/release/model.php @@ -172,7 +172,7 @@ class releaseModel extends model $this->dao->update(TABLE_RELEASE)->data($release) ->autoCheck() ->batchCheck($this->config->release->edit->requiredFields, 'notempty') - ->check('name', 'unique', "id != $releaseID AND product = {$release->product} AND branch = $branch AND deleted = '0'") + ->check('name', 'unique', "id != '$releaseID' AND product = '{$release->product}' AND branch = '$branch' AND deleted = '0'") ->where('id')->eq((int)$releaseID) ->exec(); if(!dao::isError()) diff --git a/module/release/view/browse.html.php b/module/release/view/browse.html.php index 4aa6700a97..af70c8a323 100644 --- a/module/release/view/browse.html.php +++ b/module/release/view/browse.html.php @@ -13,63 +13,69 @@ release->confirmDelete)?> -
    -
    -
    - - release->browse;?> - type !== 'normal') echo '' . $branches[$branch] . '';?> +
    +
    + -
    - id&branch=$branch");?> +
    +
    project->name;?>project->name;?> name;?>
    + + + + + + type != 'normal'):?> + + + + + + + + + + + + + + type != 'normal'):?> + + + + + + + + +
    release->id;?>release->name;?>release->build;?>product->branch;?>release->date;?>release->status;?>actions;?>
    id;?>id"), $release->name);?>createLink('build', 'view', "buildID=$release->buildID"), $release->buildName, '_blank');?>branch];?>date;?>release->statusList[$release->status];?> + id&type=story&link=true"), ' ', '', "class='btn' title='{$lang->release->linkStory}'"); + if(common::hasPriv('release', 'linkBug') and $this->config->global->flow != 'onlyStory') echo html::a(inlink('view', "releaseID=$release->id&type=bug&link=true"), ' ', '', "class='btn' title='{$lang->release->linkBug}'"); + if(common::hasPriv('release', 'changeStatus', $release)) + { + $changedStatus = $release->status == 'normal' ? 'terminate' : 'normal'; + echo html::a(inlink('changeStatus', "releaseID=$release->id&status=$changedStatus"), ' ', 'hiddenwin', "class='btn' title='{$lang->release->changeStatusList[$changedStatus]}'"); + } + common::printIcon('release', 'edit', "release=$release->id", $release, 'list'); + if(common::hasPriv('release', 'delete', $release)) + { + $deleteURL = $this->createLink('release', 'delete', "releaseID=$release->id&confirm=yes"); + echo html::a("javascript:ajaxDelete(\"$deleteURL\",\"releaseList\",confirmDelete)", '', '', "class='btn' title='{$lang->release->delete}'"); + } + ?> +
    - - - - - - - type != 'normal'):?> - - - - - - - - - - - - - - type != 'normal'):?> - - - - - - - - -
    release->id;?>release->name;?>release->build;?>product->branch;?>release->date;?>release->status;?>actions;?>
    id;?>id"), $release->name);?>createLink('build', 'view', "buildID=$release->buildID"), $release->buildName, '_blank');?>branch];?>date;?>release->statusList[$release->status];?> - id&type=story&link=true"), ' ', '', "class='btn-icon' title='{$lang->release->linkStory}'"); - if(common::hasPriv('release', 'linkBug') and $this->config->global->flow != 'onlyStory') echo html::a(inlink('view', "releaseID=$release->id&type=bug&link=true"), ' ', '', "class='btn-icon' title='{$lang->release->linkBug}'"); - if(common::hasPriv('release', 'changeStatus', $release)) - { - $changedStatus = $release->status == 'normal' ? 'terminate' : 'normal'; - echo html::a(inlink('changeStatus', "releaseID=$release->id&status=$changedStatus"), ' ', 'hiddenwin', "class='btn-icon' title='{$lang->release->changeStatusList[$changedStatus]}'"); - } - common::printIcon('release', 'edit', "release=$release->id", $release, 'list'); - if(common::hasPriv('release', 'delete', $release)) - { - $deleteURL = $this->createLink('release', 'delete', "releaseID=$release->id&confirm=yes"); - echo html::a("javascript:ajaxDelete(\"$deleteURL\",\"releaseList\",confirmDelete)", '', '', "class='btn-icon' title='{$lang->release->delete}'"); - } - ?> -
    - - + diff --git a/module/report/control.php b/module/report/control.php index 6b08d41115..b3c45f224f 100644 --- a/module/report/control.php +++ b/module/report/control.php @@ -13,13 +13,13 @@ class report extends control { /** * The index of report, goto project deviation. - * + * * @access public * @return void */ public function index() { - $this->locate(inlink('productSummary')); + $this->locate(inlink('productSummary')); } /** @@ -45,7 +45,7 @@ class report extends control /** * Product information report. - * + * * @access public * @return void */ @@ -65,9 +65,9 @@ class report extends control /** * Bug create report. - * - * @param int $begin - * @param int $end + * + * @param int $begin + * @param int $end * @access public * @return void */ @@ -88,12 +88,12 @@ class report extends control $this->view->project = $project; $this->view->product = $product; $this->view->submenu = 'test'; - $this->display(); + $this->display(); } /** * Bug assign report. - * + * * @access public * @return void */ @@ -104,34 +104,42 @@ class report extends control $this->view->submenu = 'test'; $this->view->assigns = $this->report->getBugAssign(); $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed|nodeleted'); - $this->display(); + $this->display(); } /** * Workload report. - * + * + * @param string $begin + * @param string $end + * @param int $days + * @param int $workday + * @param int $dept + * @param int $assign + * * @access public * @return void */ - public function workload($begin = '', $end = '', $days = 0, $workday = 0, $dept = 0) + public function workload($begin = '', $end = '', $days = 0, $workday = 0, $dept = 0, $assign = 'assign') { if($_POST) { - $data = fixer::input('post')->get(); - $begin = $data->begin; - $end = $data->end; - $dept = $data->dept; - $days = $data->days; - $workday = $data->workday; + $data = fixer::input('post')->get(); + $begin = $data->begin; + $end = $data->end; + $dept = $data->dept; + $days = $data->days; + $assign = $data->assign; + $workday = $data->workday; } $this->app->loadConfig('project'); - $begin = $begin ? strtotime($begin) : time(); - $end = $end ? strtotime($end) : time() + (7 * 24 * 3600); - $end += 24 * 3600; + $begin = $begin ? strtotime($begin) : time(); + $end = $end ? strtotime($end) : time() + (7 * 24 * 3600); + $end += 24 * 3600; $beginWeekDay = date('w', $begin); - $begin = date('Y-m-d', $begin); - $end = date('Y-m-d', $end); + $begin = date('Y-m-d', $begin); + $end = date('Y-m-d', $end); if(empty($workday))$workday = $this->config->project->defaultWorkhours; $diffDays = helper::diffDate($end, $begin); @@ -150,7 +158,7 @@ class report extends control $this->view->title = $this->lang->report->workload; $this->view->position[] = $this->lang->report->workload; - $this->view->workload = $this->report->getWorkload($dept); + $this->view->workload = $this->report->getWorkload($dept, $assign); $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed|nodeleted'); $this->view->depts = $this->loadModel('dept')->getOptionMenu(); $this->view->begin = $begin; @@ -158,6 +166,7 @@ class report extends control $this->view->days = $days; $this->view->workday = $workday; $this->view->dept = $dept; + $this->view->assign = $assign; $this->view->allHour = $days * $workday; $this->view->submenu = 'staff'; $this->display(); @@ -165,7 +174,7 @@ class report extends control /** * Send daily reminder mail. - * + * * @access public * @return void */ @@ -176,7 +185,7 @@ class report extends control if($this->config->report->dailyreminder->task) $tasks = $this->report->getUserTasks(); if($this->config->report->dailyreminder->todo) $todos = $this->report->getUserTodos(); if($this->config->report->dailyreminder->testTask) $testTasks = $this->report->getUserTestTasks(); - + $reminder = array(); $users = array_unique(array_merge(array_keys($bugs), array_keys($tasks), array_keys($todos), array_keys($testTasks))); @@ -216,7 +225,7 @@ class report extends control if($oldViewType == 'json') $this->viewType = 'html'; $mailContent = $this->parse('report', 'dailyreminder'); $this->viewType == $oldViewType; - + /* Send email.*/ echo date('Y-m-d H:i:s') . " sending to $user, "; $this->mail->send($user, $mailTitle, $mailContent, '', true); diff --git a/module/report/js/workload.js b/module/report/js/workload.js index 2a2d960b64..469da28ebe 100644 --- a/module/report/js/workload.js +++ b/module/report/js/workload.js @@ -9,6 +9,7 @@ function changeParams(obj) var end = $('.main .row').find('#end').val(); var workday = $('.main .row').find('#workday').val(); var dept = $('.main .row').find('#dept').val(); + var assign = $('.main .row').find('#assign').val(); var days = diffDate(begin, end); $('#days').val(days); @@ -17,23 +18,23 @@ function changeParams(obj) { var beginarray = begin.split("-"); var begin = ''; - for(i=0 ; i < beginarray.length ; i++) begin = begin + beginarray[i]; + for(i = 0; i < beginarray.length; i++) begin = begin + beginarray[i]; } if(end.indexOf('-') != -1) { var endarray = end.split("-"); var end = ''; - for(i=0 ; i < endarray.length ; i++) end = end + endarray[i]; + for(i=0 ; i < endarray.length ; i++) end = end + endarray[i]; } - link = createLink('report', 'workload', 'begin=' + begin + '&end=' + end + '&days=' + days + '&workday=' + workday + '&dept=' + dept); + var link = createLink('report', 'workload', 'begin=' + begin + '&end=' + end + '&days=' + days + '&workday=' + workday + '&dept=' + dept + '&assign=' + assign); location.href=link; } /** * Convert a date string to date object in js. - * - * @param string $date + * + * @param string $date * @access public * @return date */ @@ -45,9 +46,9 @@ function convertStringToDate(dateString) /** * Compute the diff days of two date. - * - * @param string $date1 - * @param string $date1 + * + * @param string $date1 + * @param string $date1 * @access public * @return int */ @@ -65,12 +66,12 @@ function diffDate(date1, date2) date1 += 1000 * 60 * 60 * 24; date1 = new Date(date1); } - return delta - weekEnds; + return delta - weekEnds; } $(function() { - var options = + var options = { language: config.clientLang, weekStart: 1, @@ -85,4 +86,4 @@ $(function() startDate: new Date() }; $('input#begin,input#end').fixedDate().datetimepicker(options); -}) +}); diff --git a/module/report/lang/en.php b/module/report/lang/en.php index 41855b2346..d7a56b7a91 100644 --- a/module/report/lang/en.php +++ b/module/report/lang/en.php @@ -11,7 +11,7 @@ */ $lang->report->common = 'Report'; $lang->report->index = 'Home'; -$lang->report->list = 'List'; +$lang->report->list = 'Report List'; $lang->report->item = 'Item'; $lang->report->value = 'Value'; $lang->report->percent = '%'; @@ -31,6 +31,9 @@ $lang->report->colors[] = '008ED6'; $lang->report->colors[] = '9D080D'; $lang->report->colors[] = 'A186BE'; +$lang->report->assign['noassign'] = 'Not assigned'; +$lang->report->assign['assign'] = 'Assigned'; + $lang->report->singleColor[] = 'F6BD0F'; $lang->report->projectDeviation = $lang->projectCommon . ' Deviation'; @@ -39,27 +42,27 @@ $lang->report->bugCreate = 'Bug Submission Report'; $lang->report->bugAssign = 'Bug Assignment Report'; $lang->report->workload = 'Workload'; $lang->report->workloadAB = 'Workload'; -$lang->report->bugOpenedDate = 'Bug Opened From'; +$lang->report->bugOpenedDate = 'Bug Created From'; $lang->report->taskAssignedDate = 'From'; -$lang->report->beginAndEnd = 'Date'; +$lang->report->beginAndEnd = ' From'; $lang->report->dept = 'Dept'; $lang->report->deviationChart = $lang->projectCommon . ' Deviation Chart'; -$lang->reportList->project->lists[10] = $lang->projectCommon . ' deviation|report|projectdeviation'; -$lang->reportList->product->lists[10] = $lang->productCommon . ' summary|report|productsummary'; -$lang->reportList->test->lists[10] = 'Bugs|report|bugcreate'; +$lang->reportList->project->lists[10] = $lang->projectCommon . ' Deviation|report|projectdeviation'; +$lang->reportList->product->lists[10] = $lang->productCommon . ' Summary|report|productsummary'; +$lang->reportList->test->lists[10] = 'Bugs Creation|report|bugcreate'; $lang->reportList->test->lists[13] = 'Bug Assignment|report|bugassign'; $lang->reportList->staff->lists[10] = 'Workload|report|workload'; $lang->report->id = 'ID'; $lang->report->project = $lang->projectCommon; $lang->report->product = $lang->productCommon; -$lang->report->user = 'Username'; +$lang->report->user = 'Name'; $lang->report->bugTotal = 'Bug'; $lang->report->task = 'Task'; -$lang->report->estimate = 'Hour'; -$lang->report->consumed = 'Consumed'; -$lang->report->remain = 'Remained'; +$lang->report->estimate = 'Est.(h)'; +$lang->report->consumed = 'Cost'; +$lang->report->remain = 'Left'; $lang->report->deviation = 'Deviation'; $lang->report->deviationRate = 'Deviation Rate'; $lang->report->total = 'Total'; @@ -72,23 +75,28 @@ $lang->report->unplanned = 'Unplanned'; $lang->report->workday = 'Hours/Day'; $lang->report->diffDays = 'Man-Day'; +$lang->report->typeList[''] = 'Default'; +$lang->report->typeList['pie'] = 'Pie'; +$lang->report->typeList['bar'] = 'Bar'; +$lang->report->typeList['line'] = 'Line'; + $lang->report->conditions = 'Filter by:'; $lang->report->closedProduct = 'Closed ' . $lang->productCommon; -$lang->report->overduePlan = 'Overdue Plan'; +$lang->report->overduePlan = 'Expired Plan'; /* daily reminder. */ $lang->report->idAB = 'ID'; $lang->report->bugTitle = 'Bug Title'; $lang->report->taskName = 'Task Name'; -$lang->report->todoName = 'To-Do Name'; +$lang->report->todoName = 'Todo Name'; $lang->report->testTaskName = 'Test Task Name'; $lang->report->deadline = 'Deadline'; $lang->report->mailTitle = new stdclass(); $lang->report->mailTitle->begin = 'Notice: You have'; -$lang->report->mailTitle->bug = " Bug(%s),"; -$lang->report->mailTitle->task = " Task(%s),"; -$lang->report->mailTitle->todo = " To-Do(%s),"; -$lang->report->mailTitle->testTask = " Test Task(%s),"; +$lang->report->mailTitle->bug = " Bug (%s),"; +$lang->report->mailTitle->task = " Task (%s),"; +$lang->report->mailTitle->todo = " Todo (%s),"; +$lang->report->mailTitle->testTask = " Test Task (%s),"; $lang->report->proVersion = 'Try ZenTao Pro for more!'; diff --git a/module/report/lang/zh-cn.php b/module/report/lang/zh-cn.php index 0965b08343..e638c08276 100644 --- a/module/report/lang/zh-cn.php +++ b/module/report/lang/zh-cn.php @@ -31,6 +31,9 @@ $lang->report->colors[] = '008ED6'; $lang->report->colors[] = '9D080D'; $lang->report->colors[] = 'A186BE'; +$lang->report->assign['noassign'] = '未指派'; +$lang->report->assign['assign'] = '已指派'; + $lang->report->singleColor[] = 'F6BD0F'; $lang->report->projectDeviation = $lang->projectCommon . '偏差报表'; @@ -72,6 +75,11 @@ $lang->report->unplanned = '未计划'; $lang->report->workday = '每天工时'; $lang->report->diffDays = '工作日天数'; +$lang->report->typeList[''] = '默认'; +$lang->report->typeList['pie'] = '饼图'; +$lang->report->typeList['bar'] = '柱状图'; +$lang->report->typeList['line'] = '折线图'; + $lang->report->conditions = '筛选条件:'; $lang->report->closedProduct = '关闭' . $lang->productCommon; $lang->report->overduePlan = '过期计划'; diff --git a/module/report/lang/zh-tw.php b/module/report/lang/zh-tw.php index 051651dfd8..5bd985c463 100644 --- a/module/report/lang/zh-tw.php +++ b/module/report/lang/zh-tw.php @@ -31,6 +31,9 @@ $lang->report->colors[] = '008ED6'; $lang->report->colors[] = '9D080D'; $lang->report->colors[] = 'A186BE'; +$lang->report->assign['noassign'] = '未指派'; +$lang->report->assign['assign'] = '已指派'; + $lang->report->singleColor[] = 'F6BD0F'; $lang->report->projectDeviation = $lang->projectCommon . '偏差報表'; @@ -72,6 +75,11 @@ $lang->report->unplanned = '未計劃'; $lang->report->workday = '每天工時'; $lang->report->diffDays = '工作日天數'; +$lang->report->typeList[''] = '預設'; +$lang->report->typeList['pie'] = '餅圖'; +$lang->report->typeList['bar'] = '柱狀圖'; +$lang->report->typeList['line'] = '折線圖'; + $lang->report->conditions = '篩選條件:'; $lang->report->closedProduct = '關閉' . $lang->productCommon; $lang->report->overduePlan = '過期計劃'; diff --git a/module/report/model.php b/module/report/model.php index a52a888639..8c6436b731 100644 --- a/module/report/model.php +++ b/module/report/model.php @@ -15,8 +15,8 @@ class reportModel extends model { /** * Compute percent of every item. - * - * @param array $datas + * + * @param array $datas * @access public * @return array */ @@ -69,9 +69,9 @@ class reportModel extends model /** * Convert date format. - * - * @param array $dateList - * @param string $format + * + * @param array $dateList + * @param string $format * @access public * @return array */ @@ -82,8 +82,8 @@ class reportModel extends model } /** - * Get projects. - * + * Get projects. + * * @access public * @return void */ @@ -121,10 +121,10 @@ class reportModel extends model } /** - * Get products. - * + * Get products. + * * @access public - * @return array + * @return array */ public function getProducts($conditions) { @@ -195,10 +195,10 @@ class reportModel extends model } /** - * Get bugs - * - * @param int $begin - * @param int $end + * Get bugs + * + * @param int $begin + * @param int $end * @access public * @return array */ @@ -232,20 +232,55 @@ class reportModel extends model $bugCreate[$account]['validRate'] = (isset($bug['resolved']) and $bug['resolved']) ? ($validRate / $bug['resolved']) : "0"; } uasort($bugCreate, 'sortSummary'); - return $bugCreate; + return $bugCreate; } /** - * Get workload. - * + * Get workload. + * + * @param int $dept + * @param string $assign + * * @access public * @return array */ - public function getWorkload($dept = 0) + public function getWorkload($dept = 0, $assign = 'assign') { $depts = array(); if($dept) $depts = $this->loadModel('dept')->getAllChildId($dept); + if($assign == 'noassign') + { + $members = $this->dao->select('t1.account,t2.name,t1.root')->from(TABLE_TEAM)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t2.id = t1.root') + ->leftJoin(TABLE_USER)->alias('t3')->on('t3.account = t1.account') + ->where('t2.status')->notin('cancel, closed, done, suspended') + ->beginIF($dept)->andWhere('t3.dept')->in($depts)->fi() + ->andWhere('t1.type')->eq('project') + ->andWhere("t1.account NOT IN(SELECT `assignedTo` FROM " . TABLE_TASK . " WHERE `project` = t1.`root` AND `status` NOT IN('cancel, closed, done, pause') AND assignedTo != '' GROUP BY assignedTo)") + ->fetchGroup('account', 'name'); + + $workload = array(); + if(!empty($members)) + { + foreach($members as $member => $projects) + { + if(!empty($projects)) + { + foreach($projects as $name => $project) + { + $workload[$member]['task'][$name]['count'] = 0; + $workload[$member]['task'][$name]['manhour'] = 0; + $workload[$member]['task'][$name]['projectID'] = $project->root; + $workload[$member]['total']['count'] = 0; + $workload[$member]['total']['manhour'] = 0; + } + } + } + } + return $workload; + } + $tasks = $this->dao->select('t1.*, t2.name as projectName')->from(TABLE_TASK)->alias('t1') ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') ->leftJoin(TABLE_USER)->alias('t3')->on('t1.assignedTo = t3.account') @@ -254,7 +289,23 @@ class reportModel extends model ->andWhere('t2.deleted')->eq(0) ->andWhere('t2.status')->notin('cancel, closed, done, suspended') ->beginIF($dept)->andWhere('t3.dept')->in($depts)->fi() - ->fetchGroup('assignedTo'); + ->fetchGroup('assignedTo', 'id'); + + if(empty($tasks)) return array(); + + /* Fix bug for children. */ + $parents = array(); + foreach($tasks as $user => $userTasks) + { + if($user) + { + foreach($userTasks as $task) + { + if(!empty($task->parent)) $parents[$task->parent] = $task->parent; + } + } + } + $workload = array(); foreach($tasks as $user => $userTasks) { @@ -262,11 +313,12 @@ class reportModel extends model { foreach($userTasks as $task) { + if(!empty($parents) && in_array($task->id, $parents)) continue; $workload[$user]['task'][$task->projectName]['count'] = isset($workload[$user]['task'][$task->projectName]['count']) ? $workload[$user]['task'][$task->projectName]['count'] + 1 : 1; $workload[$user]['task'][$task->projectName]['manhour'] = isset($workload[$user]['task'][$task->projectName]['manhour']) ? $workload[$user]['task'][$task->projectName]['manhour'] + $task->left : $task->left; $workload[$user]['task'][$task->projectName]['projectID'] = $task->project; - $workload[$user]['total']['count'] = isset($workload[$user]['total']['count']) ? $workload[$user]['total']['count'] + 1 : 1; - if($task->parent == 0) $workload[$user]['total']['manhour'] = isset($workload[$user]['total']['manhour']) ? $workload[$user]['total']['manhour'] + $task->left : $task->left; + $workload[$user]['total']['count'] = isset($workload[$user]['total']['count']) ? $workload[$user]['total']['count'] + 1 : 1; + $workload[$user]['total']['manhour'] = isset($workload[$user]['total']['manhour']) ? $workload[$user]['total']['manhour'] + $task->left : $task->left; } } } @@ -275,10 +327,10 @@ class reportModel extends model } /** - * Get bug assign. - * + * Get bug assign. + * * @access public - * @return array + * @return array */ public function getBugAssign() { @@ -307,7 +359,7 @@ class reportModel extends model /** * Get System URL. - * + * * @access public * @return void */ @@ -331,13 +383,13 @@ class reportModel extends model /** * Get user bugs. - * + * * @access public * @return void */ public function getUserBugs() { - $bugs = $this->dao->select('t1.id, t1.title, t2.account as user, t1.deadline') + return $this->dao->select('t1.id, t1.title, t2.account as user, t1.deadline') ->from(TABLE_BUG)->alias('t1') ->leftJoin(TABLE_USER)->alias('t2') ->on('t1.assignedTo = t2.account') @@ -345,19 +397,21 @@ class reportModel extends model ->andWhere('t1.assignedTo')->ne('closed') ->andWhere('t1.deleted')->eq(0) ->andWhere('t2.deleted')->eq(0) + ->andWhere('t1.deadline', true)->eq('0000-00-00') + ->orWhere('t1.deadline')->lt(date(DT_DATE1, strtotime('+4 day'))) + ->markRight(1) ->fetchGroup('user'); - return $bugs; } /** * Get user tasks. - * + * * @access public * @return void */ public function getUserTasks() { - $tasks = $this->dao->select('t1.id, t1.name, t2.account as user, t1.deadline')->from(TABLE_TASK)->alias('t1') + return $this->dao->select('t1.id, t1.name, t2.account as user, t1.deadline')->from(TABLE_TASK)->alias('t1') ->leftJoin(TABLE_USER)->alias('t2')->on('t1.assignedTo = t2.account') ->leftJoin(TABLE_PROJECT)->alias('t3')->on('t1.project = t3.id') ->where('t1.assignedTo')->ne('') @@ -365,16 +419,17 @@ class reportModel extends model ->andWhere('t2.deleted')->eq(0) ->andWhere('t1.status')->in('wait, doing') ->andWhere('t3.status')->ne('suspended') + ->andWhere('t1.deadline', true)->eq('0000-00-00') + ->orWhere('t1.deadline')->lt(date(DT_DATE1, strtotime('+4 day'))) + ->markRight(1) ->fetchGroup('user'); - - return $tasks; } /** * Get user todos. - * + * * @access public - * @return void + * @return array */ public function getUserTodos() { @@ -398,7 +453,7 @@ class reportModel extends model /** * Get user testTasks. - * + * * @access public * @return array */ @@ -413,6 +468,12 @@ class reportModel extends model } } +/** + * @param $pre + * @param $next + * + * @return int + */ function sortSummary($pre, $next) { if($pre['validRate'] == $next['validRate']) return 0; diff --git a/module/report/view/bugcreate.html.php b/module/report/view/bugcreate.html.php index d2e206329d..70acfa6bb5 100644 --- a/module/report/view/bugcreate.html.php +++ b/module/report/view/bugcreate.html.php @@ -45,7 +45,7 @@
    bug->resolutionList['notrepro'];?> bug->resolutionList['postponed'];?> bug->resolutionList['willnotfix'];?>bug->resolutionList['tostory'];?>bug->resolutionList['tostory'];?> report->validRate;?> report->total;?>
    product->name;?> product->PO;?> productplan->common;?>productplan->begin;?>productplan->end;?>productplan->begin;?>productplan->end;?> story->statusList['draft'];?> story->statusList['active'];?> story->statusList['changed'];?>
    " . html::a($this->createLink('product', 'view', "product=$product->id"), $product->name) . "

    ";?>
    " . $users[$product->PO] . '

    ';?>
    " . zget($users, $product->PO) . '

    ';?>
    + + + + + + + + + + + + score->rule as $module => $moduleRule):?> + $rule):?> + + + + + + + + + + + +
    score->module;?>score->method;?>score->times;?>score->hour;?>score->score;?>score->desc;?>
    score->modules[$module];?>score->methods[$module][$method];?>score->noLimit : $rule['times'];?>score->noLimit : $rule['hour'];?> + score->extended[$module][$method])) + { + $desc = $lang->score->extended[$module][$method]; + $descRule = explode('##', $desc); + if(!empty($descRule)) + { + foreach($descRule as $key => $value) + { + if($key % 2 == 1) + { + $match = explode(',', $value); + if(count($match) == 2) + { + $score = $config->score->ruleExtended[$module][$method][$match[0]][$match[1]]; + } + else + { + $score = $config->score->ruleExtended[$module][$method][$match[0]]; + } + $desc = str_replace('##' . $value . '##', $score, $desc); + } + } + } + echo $desc; + } + ?> +
    + - - - - - - - - - - - - - - score->rule as $module => $moduleRule):?> - $rule):?> - - - - - - - - - - - -
    score->module;?>score->method;?>score->times;?>score->hour;?>score->score;?>score->desc;?>
    score->modules[$module];?>score->methods[$module][$method];?>score->noLimit : $rule['times'];?>score->noLimit : $rule['hour'];?> - score->extended[$module][$method])) - { - $desc = $lang->score->extended[$module][$method]; - $descRule = explode('##', $desc); - if(!empty($descRule)) - { - foreach($descRule as $key => $value) - { - if($key % 2 == 1) - { - $match = explode(',', $value); - if(count($match) == 2) - { - $score = $config->score->ruleExtended[$module][$method][$match[0]][$match[1]]; - } - else - { - $score = $config->score->ruleExtended[$module][$method][$match[0]]; - } - $desc = str_replace('##' . $value . '##', $score, $desc); - } - } - } - echo $desc; - } - ?> -
    + diff --git a/module/search/lang/en.php b/module/search/lang/en.php index 4564626295..0868ec317f 100644 --- a/module/search/lang/en.php +++ b/module/search/lang/en.php @@ -13,13 +13,13 @@ $lang->search->common = 'Search'; $lang->search->reset = 'Reset'; $lang->search->saveQuery = 'Save'; $lang->search->myQuery = 'My Queries'; -$lang->search->group1 = '1'; -$lang->search->group2 = '2'; +$lang->search->group1 = 'Group 1'; +$lang->search->group2 = 'Group 2'; $lang->search->buildForm = 'Search Form'; $lang->search->buildQuery = 'Execute Query'; -$lang->search->saveQuery = 'Save'; -$lang->search->deleteQuery = 'Delete'; -$lang->search->setQueryTitle = 'Please enter the title( Save it before searching.):'; +$lang->search->saveQuery = 'Save Query'; +$lang->search->deleteQuery = 'Delete Query'; +$lang->search->setQueryTitle = 'Enter the query title. Save it After searching.'; $lang->search->select = 'Stories/Tasks Filter'; $lang->search->me = 'Me'; $lang->search->noQuery = 'No query saved!'; diff --git a/module/search/view/buildform.html.php b/module/search/view/buildform.html.php index 0934964a27..81f6499ae9 100644 --- a/module/search/view/buildform.html.php +++ b/module/search/view/buildform.html.php @@ -44,8 +44,9 @@ include '../../common/view/chosen.html.php'; #searchlite {line-height: 127px} #searchform.showmore #searchmore, #searchform #searchlite {display: none;} #searchform.showmore #searchlite, #searchform #searchmore {display: inline-block;} -#searchform .chosen-container .chosen-single{max-width: 170px;} -#searchform .chosen-container .chosen-drop{min-width: 400px;} +#searchform .chosen-container[id^="field"] .chosen-drop{min-width: 120px;} +#searchform [id^="valueBox"] .chosen-container .chosen-single{max-width: 170px;} +#searchform [id^="valueBox"] .chosen-container .chosen-drop{min-width: 400px;} #searchform .chosen-container .chosen-drop ul.chosen-results li{white-space:normal} #searchmore > i, #searchlite > i {font-size: 28px;} #searchmore > i {position: relative; top: 4px;} @@ -376,7 +377,7 @@ foreach($fieldParams as $fieldName => $param) echo ''; /* Print field. */ - echo "" . html::select("field$fieldNO", $searchFields, $formSession["field$fieldNO"], "onchange='setField(this, $fieldNO, {$module}params)' class='form-control'") . ''; + echo "" . html::select("field$fieldNO", $searchFields, $formSession["field$fieldNO"], "onchange='setField(this, $fieldNO, {$module}params)' class='form-control chosen'") . ''; /* Print operator. */ echo "" . html::select("operator$fieldNO", $lang->search->operators, $formSession["operator$fieldNO"], "class='form-control'") . ''; @@ -435,7 +436,7 @@ foreach($fieldParams as $fieldName => $param) echo ''; /* Print field. */ - echo "" . html::select("field$fieldNO", $searchFields, $formSession["field$fieldNO"], "onchange='setField(this, $fieldNO, {$module}params)' class='form-control'") . ''; + echo "" . html::select("field$fieldNO", $searchFields, $formSession["field$fieldNO"], "onchange='setField(this, $fieldNO, {$module}params)' class='form-control chosen'") . ''; /* Print operator. */ echo "" . html::select("operator$fieldNO", $lang->search->operators, $formSession["operator$fieldNO"], "class='form-control'") . ''; diff --git a/module/story/config.php b/module/story/config.php index f6db8e00e8..3c117df04c 100644 --- a/module/story/config.php +++ b/module/story/config.php @@ -38,8 +38,8 @@ $config->story->list->exportFields = ' childStories, linkStories, duplicateStory, files'; $config->story->list->customCreateFields = 'source,verify,pri,estimate,mailto,keywords'; -$config->story->list->customBatchCreateFields = 'module,plan,spec,source,verify,pri,estimate,review,keywords'; -$config->story->list->customBatchEditFields = 'branch,module,plan,estimate,pri,assignedTo,source,stage,closedBy,closedReason,keywords'; +$config->story->list->customBatchCreateFields = 'plan,spec,source,verify,pri,estimate,review,keywords'; +$config->story->list->customBatchEditFields = 'branch,plan,estimate,pri,assignedTo,source,stage,closedBy,closedReason,keywords'; $config->story->custom = new stdclass(); $config->story->custom->createFields = $config->story->list->customCreateFields; @@ -91,12 +91,12 @@ $config->story->datatable->fieldList['sourceNote']['required'] = 'no'; $config->story->datatable->fieldList['status']['title'] = 'statusAB'; $config->story->datatable->fieldList['status']['fixed'] = 'no'; -$config->story->datatable->fieldList['status']['width'] = '50'; +$config->story->datatable->fieldList['status']['width'] = '60'; $config->story->datatable->fieldList['status']['required'] = 'no'; $config->story->datatable->fieldList['estimate']['title'] = 'estimateAB'; $config->story->datatable->fieldList['estimate']['fixed'] = 'no'; -$config->story->datatable->fieldList['estimate']['width'] = '50'; +$config->story->datatable->fieldList['estimate']['width'] = '55'; $config->story->datatable->fieldList['estimate']['required'] = 'no'; $config->story->datatable->fieldList['stage']['title'] = 'stageAB'; diff --git a/module/story/control.php b/module/story/control.php index 6defe6006a..cd47d513af 100644 --- a/module/story/control.php +++ b/module/story/control.php @@ -37,10 +37,11 @@ class story extends control * @param int $projectID * @param int $bugID * @param int $planID + * @param int $todoID * @access public * @return void */ - public function create($productID = 0, $branch = 0, $moduleID = 0, $storyID = 0, $projectID = 0, $bugID = 0, $planID = 0) + public function create($productID = 0, $branch = 0, $moduleID = 0, $storyID = 0, $projectID = 0, $bugID = 0, $planID = 0, $todoID = 0) { if(!empty($_POST)) { @@ -73,7 +74,12 @@ class story extends control $action = $bugID == 0 ? 'Opened' : 'Frombug'; $extra = $bugID == 0 ? '' : $bugID; $actionID = $this->action->create('story', $storyID, $action, '', $extra); - $this->story->sendmail($storyID, $actionID); + + if($todoID > 0) + { + $this->dao->update(TABLE_TODO)->set('status')->eq('done')->where('id')->eq($todoID)->exec(); + $this->action->create('todo', $todoID, 'finished', '', "STORY:$storyID"); + } if($this->post->newStory) { @@ -156,6 +162,15 @@ class story extends control } } + if($todoID > 0) + { + $todo = $this->loadModel('todo')->getById($todoID); + $source = 'todo'; + $title = $todo->name; + $spec = $todo->desc; + $pri = $todo->pri; + } + /* Set Custom*/ foreach(explode(',', $this->config->story->list->customCreateFields) as $field) $customFields[$field] = $this->lang->story->$field; $this->view->customFields = $customFields; @@ -211,11 +226,7 @@ class story extends control if(dao::isError()) die(js::error(dao::getError())); $stories = array(); - foreach($mails as $mail) - { - $stories[] = $mail->storyID; - if($mail->actionID) $this->story->sendmail($mail->storyID, $mail->actionID); - } + foreach($mails as $mail) $stories[] = $mail->storyID; if($project) $this->loadModel('project')->linkStory($project, $stories); /* If storyID not equal zero, subdivide this story to child stories and close it. */ @@ -225,7 +236,6 @@ class story extends control $actionID = $this->story->subdivide($storyID, $mails); if(dao::isError()) die(js::error(dao::getError())); - $this->story->sendmail($storyID, $actionID); if(isonlybody()) die(js::closeModal('parent.parent', 'this')); die(js::locate(inlink('view', "storyID=$storyID"), 'parent')); @@ -243,11 +253,11 @@ class story extends control $this->product->setMenu($products, $product->id, $branch); /* Init vars. */ - $planID = $plan; - $pri = 0; - $estimate = ''; - $title = ''; - $spec = ''; + $planID = $plan; + $pri = 0; + $estimate = ''; + $title = ''; + $spec = ''; /* Process upload images. */ if($this->session->storyImagesFile) @@ -359,7 +369,6 @@ class story extends control $action = !empty($changes) ? 'Edited' : 'Commented'; $actionID = $this->action->create('story', $storyID, $action, $this->post->comment); $this->action->logHistory($actionID, $changes); - $this->story->sendmail($storyID, $actionID); } die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); } @@ -403,7 +412,6 @@ class story extends control $actionID = $this->action->create('story', $storyID, 'Edited'); $this->action->logHistory($actionID, $changes); - $this->story->sendmail($storyID, $actionID); } } die(js::locate($this->session->storyList, 'parent')); @@ -537,7 +545,6 @@ class story extends control if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ; $actionID = $this->action->create('story', $storyID, $action, $fileAction . $this->post->comment); $this->action->logHistory($actionID, $changes); - $this->story->sendmail($storyID, $actionID); } die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); } @@ -571,7 +578,6 @@ class story extends control $this->story->activate($storyID); if(dao::isError()) die(js::error(dao::getError())); $actionID = $this->action->create('story', $storyID, 'Activated', $this->post->comment); - $this->story->sendmail($storyID, $actionID); if(isonlybody()) die(js::closeModal('parent.parent', 'this')); die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); @@ -681,7 +687,6 @@ class story extends control $result = $this->post->result; if($this->post->closedReason != '' and strpos('done,postponed,subdivided,willnotdo', $this->post->closedReason) === false) $result = 'pass'; $actionID = $this->action->create('story', $storyID, 'Reviewed', $this->post->comment, ucfirst($result)); - $this->story->sendmail($storyID, $actionID); if($this->post->result == 'reject') { $this->action->create('story', $storyID, 'Closed', '', ucfirst($this->post->closedReason)); @@ -735,7 +740,6 @@ class story extends control $actions = $this->story->batchReview($storyIDList, $result, $reason); if(dao::isError()) die(js::error(dao::getError())); - foreach($actions as $storyID => $actionID) $this->story->sendmail($storyID, $actionID); if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther'); die(js::locate($this->session->storyList, 'parent')); } @@ -755,7 +759,6 @@ class story extends control if(dao::isError()) die(js::error(dao::getError())); $actionID = $this->action->create('story', $storyID, 'Closed', $this->post->comment, ucfirst($this->post->closedReason) . ($this->post->duplicateStory ? ':' . (int)$this->post->duplicateStory : '')); $this->action->logHistory($actionID, $changes); - $this->story->sendmail($storyID, $actionID); if(isonlybody()) die(js::closeModal('parent.parent', 'this')); die(js::locate(inlink('view', "storyID=$storyID"), 'parent')); } @@ -802,7 +805,6 @@ class story extends control { $actionID = $this->action->create('story', $storyID, 'Closed', htmlspecialchars($this->post->comments[$storyID]), ucfirst($this->post->closedReasons[$storyID]) . ($this->post->duplicateStoryIDList[$storyID] ? ':' . (int)$this->post->duplicateStoryIDList[$storyID] : '')); $this->action->logHistory($actionID, $changes); - $this->story->sendmail($storyID, $actionID); } } if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther'); @@ -883,7 +885,6 @@ class story extends control { $actionID = $this->action->create('story', $storyID, 'Edited'); $this->action->logHistory($actionID, $changes); - $this->story->sendmail($storyID, $actionID); } if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther'); die(js::reload('parent')); @@ -906,7 +907,6 @@ class story extends control { $actionID = $this->action->create('story', $storyID, 'Edited'); $this->action->logHistory($actionID, $changes); - $this->story->sendmail($storyID, $actionID); } if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther'); die(js::reload('parent')); @@ -929,7 +929,6 @@ class story extends control { $actionID = $this->action->create('story', $storyID, 'Edited'); $this->action->logHistory($actionID, $changes); - $this->story->sendmail($storyID, $actionID); } if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther'); die(js::reload('parent')); @@ -954,7 +953,6 @@ class story extends control { $actionID = $this->action->create('story', $storyID, $action); $this->action->logHistory($actionID, $changes); - $this->story->sendmail($storyID, $actionID); } if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther'); die(js::locate($this->session->storyList, 'parent')); @@ -976,7 +974,6 @@ class story extends control { $actionID = $this->action->create('story', $storyID, 'Edited'); $this->action->logHistory($actionID, $changes); - $this->story->sendmail($storyID, $actionID); } } if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther'); @@ -1314,7 +1311,7 @@ class story extends control * @access public * @return void */ - public function report($productID, $browseType, $branchID, $moduleID) + public function report($productID, $browseType, $branchID, $moduleID, $chartType = 'pie') { $this->loadModel('report'); $this->view->charts = array(); @@ -1326,9 +1323,9 @@ class story extends control $chartFunc = 'getDataOf' . $chart; $chartData = $this->story->$chartFunc(); $chartOption = $this->lang->story->report->$chart; + if(!empty($chartType)) $chartOption->type = $chartType; $this->story->mergeChartOption($chart); - $this->view->charts[$chart] = $chartOption; $this->view->datas[$chart] = $this->report->computePercent($chartData); } @@ -1340,8 +1337,10 @@ class story extends control $this->view->position[] = $this->products[$productID]; $this->view->position[] = $this->lang->story->reportChart; $this->view->productID = $productID; + $this->view->branchID = $branchID; $this->view->browseType = $browseType; $this->view->moduleID = $moduleID; + $this->view->chartType = $chartType; $this->view->checkedCharts = $this->post->charts ? join(',', $this->post->charts) : ''; $this->display(); } diff --git a/module/story/js/batchedit.js b/module/story/js/batchedit.js index 2faf80e809..864b39fb39 100644 --- a/module/story/js/batchedit.js +++ b/module/story/js/batchedit.js @@ -30,11 +30,11 @@ function loadBranches(product, branch, storyID) if(typeof(branch) == 'undefined') branch = 0; if(!branch) branch = 0; - moduleLink = createLink('tree', 'ajaxGetOptionMenu', 'productID=' + product + '&viewtype=story&branch=' + branch + '&rootModuleID=0&returnType=html&fieldID=' + storyID + '&needManage=true'); - $('#modules' + storyID).parent('td').load(moduleLink, function(){$('#modules' + storyID).chosen(defaultChosenOptions);}) + moduleLink = createLink('tree', 'ajaxGetOptionMenu', 'productID=' + product + '&viewtype=story&branch=' + branch + '&rootModuleID=0&returnType=html&fieldID=' + storyID); + $('#modules' + storyID).parent('td').load(moduleLink, function(){$('#modules' + storyID).chosen(defaultChosenOptions);}); planID = $('#plans' + storyID).val(); - planLink = createLink('product', 'ajaxGetPlans', 'productID=' + product + '&branch=' + branch + '&planID=' + planID + '&fieldID=' + storyID + '&needCreate=true'); + planLink = createLink('product', 'ajaxGetPlans', 'productID=' + product + '&branch=' + branch + '&planID=' + planID + '&fieldID=' + storyID); $('#plans' + storyID).parent('td').load(planLink, function(){$('#plans' + storyID).chosen(defaultChosenOptions);}); } diff --git a/module/story/js/report.js b/module/story/js/report.js index 38276947f3..2c8ef3ee94 100644 --- a/module/story/js/report.js +++ b/module/story/js/report.js @@ -12,3 +12,9 @@ $(function() fixedTableHead('.table-wrapper'); $(window).resize(resizeChartTable); }); + +function changeChartType(type) +{ + $('form').attr('action', createLink('story', 'report', 'productID=' + productID + '&browseType=' + browseType + '&branchID=' + branchID + '&moduleID=' + moduleID + '&chartType=' + type)); + $('form').find('#submit').click(); +} diff --git a/module/story/lang/en.php b/module/story/lang/en.php index f07f6418ce..3cc8b6a497 100644 --- a/module/story/lang/en.php +++ b/module/story/lang/en.php @@ -9,7 +9,7 @@ * @version $Id: en.php 5141 2013-07-15 05:57:15Z chencongzhi520@gmail.com $ * @link http://www.zentao.net */ -$lang->story->create = "Story"; +$lang->story->create = "Create Story"; $lang->story->batchCreate = "Batch Create"; $lang->story->change = "Change"; $lang->story->changed = 'Change'; @@ -35,8 +35,8 @@ $lang->story->caseCountAB = 'C'; $lang->story->linkStory = 'Link'; $lang->story->unlinkStory = 'UnLinked'; $lang->story->export = "Export Data"; -$lang->story->zeroCase = "Zero Case"; -$lang->story->zeroTask = "Zero Task"; +$lang->story->zeroCase = "Stories without cases"; +$lang->story->zeroTask = "Only Show Stories without tasks"; $lang->story->reportChart = "Report"; $lang->story->copyTitle = "Copy Title"; $lang->story->batchChangePlan = "Batch Change Plans"; @@ -58,25 +58,25 @@ $lang->story->title = 'Title'; $lang->story->spec = 'Description'; $lang->story->verify = 'Acceptance'; $lang->story->pri = 'Priority'; -$lang->story->estimate = 'Hour'; -$lang->story->estimateAB = 'Hour'; +$lang->story->estimate = 'Est.(h)'; +$lang->story->estimateAB = 'Est.(h)'; $lang->story->hour = 'Hour'; $lang->story->status = 'Status'; $lang->story->stage = 'Stage'; $lang->story->stageAB = 'Stage'; $lang->story->mailto = 'Mailto'; -$lang->story->openedBy = 'Open By'; -$lang->story->openedDate = 'Open on'; +$lang->story->openedBy = 'Creator'; +$lang->story->openedDate = 'Create on'; $lang->story->assignedTo = 'Assignee'; -$lang->story->assignedDate = 'Assigned On'; -$lang->story->lastEditedBy = 'Last Edited By'; -$lang->story->lastEditedDate = 'Last Edited On'; -$lang->story->closedBy = 'Closed By'; -$lang->story->closedDate = 'Closed On'; -$lang->story->closedReason = 'Reason'; +$lang->story->assignedDate = 'Assigned on'; +$lang->story->lastEditedBy = 'Last Edited'; +$lang->story->lastEditedDate = 'Edited on'; +$lang->story->closedBy = 'Closed by'; +$lang->story->closedDate = 'Closed on'; +$lang->story->closedReason = 'Close Reason'; $lang->story->rejectedReason = 'Reject Reason'; $lang->story->reviewedBy = 'Reviewer'; -$lang->story->reviewedDate = 'Review on'; +$lang->story->reviewedDate = 'Reviewed on'; $lang->story->version = 'Version'; $lang->story->plan = 'Plan'; $lang->story->planAB = 'Plan'; @@ -114,15 +114,16 @@ $lang->story->stageList['testing'] = 'Testing'; $lang->story->stageList['tested'] = 'Tested'; $lang->story->stageList['verified'] = 'Accepted'; $lang->story->stageList['released'] = 'Released'; +$lang->story->stageList['closed'] = 'Closed'; $lang->story->reasonList[''] = ''; $lang->story->reasonList['done'] = 'Done'; $lang->story->reasonList['subdivided'] = 'Decomposed'; -$lang->story->reasonList['duplicate'] = 'Duplicate'; +$lang->story->reasonList['duplicate'] = 'Duplicated'; $lang->story->reasonList['postponed'] = 'Postponed'; $lang->story->reasonList['willnotdo'] = "Ignore"; $lang->story->reasonList['cancel'] = 'Cancelled'; -$lang->story->reasonList['bydesign'] = 'Default Design'; +$lang->story->reasonList['bydesign'] = 'By Design'; //$lang->story->reasonList['isbug'] = 'Bug!'; $lang->story->reviewResultList[''] = ''; @@ -141,7 +142,7 @@ $lang->story->sourceList['po'] = $lang->productCommon . ' Owner'; $lang->story->sourceList['market'] = 'Marketing'; $lang->story->sourceList['service'] = 'Customer Service'; $lang->story->sourceList['operation'] = 'Operations'; -$lang->story->sourceList['support'] = 'Technical support'; +$lang->story->sourceList['support'] = 'Technical Support'; $lang->story->sourceList['competitor'] = 'Competitor'; $lang->story->sourceList['partner'] = 'Partner'; $lang->story->sourceList['dev'] = 'Dev Team'; @@ -160,7 +161,7 @@ $lang->story->legendLifeTime = 'Story Life '; $lang->story->legendRelated = 'Related Info'; $lang->story->legendMailto = 'Mail To'; $lang->story->legendAttatch = 'Files'; -$lang->story->legendProjectAndTask = $lang->projectCommon . 'Task'; +$lang->story->legendProjectAndTask = $lang->projectCommon . ' Task'; $lang->story->legendBugs = 'Linked Bug'; $lang->story->legendFromBug = 'From Bug'; $lang->story->legendCases = 'Linked Case'; @@ -213,22 +214,22 @@ $lang->story->action->unlinkchildstory = array('main' => '$date, unlinked by /* 统计报表。*/ $lang->story->report = new stdclass(); $lang->story->report->common = 'Report'; -$lang->story->report->select = 'Select the type of Story Report'; +$lang->story->report->select = 'Group Stories by'; $lang->story->report->create = 'Generate'; $lang->story->report->value = 'Story Count'; -$lang->story->report->charts['storysPerProduct'] = 'per ' . $lang->productCommon; -$lang->story->report->charts['storysPerModule'] = 'per Module'; -$lang->story->report->charts['storysPerSource'] = 'per Source'; -$lang->story->report->charts['storysPerPlan'] = 'per Plan'; -$lang->story->report->charts['storysPerStatus'] = 'per Status'; -$lang->story->report->charts['storysPerStage'] = 'per Stage'; -$lang->story->report->charts['storysPerPri'] = 'per Priority'; -$lang->story->report->charts['storysPerEstimate'] = 'per Hour'; -$lang->story->report->charts['storysPerOpenedBy'] = 'per CreatedBy'; -$lang->story->report->charts['storysPerAssignedTo'] = 'per Assignee'; -$lang->story->report->charts['storysPerClosedReason'] = 'per Closed Reason'; -$lang->story->report->charts['storysPerChange'] = 'per Change'; +$lang->story->report->charts['storysPerProduct'] = 'by ' . $lang->productCommon; +$lang->story->report->charts['storysPerModule'] = 'by Module'; +$lang->story->report->charts['storysPerSource'] = 'by Source'; +$lang->story->report->charts['storysPerPlan'] = 'by Plan'; +$lang->story->report->charts['storysPerStatus'] = 'by Status'; +$lang->story->report->charts['storysPerStage'] = 'by Stage'; +$lang->story->report->charts['storysPerPri'] = 'by Priority'; +$lang->story->report->charts['storysPerEstimate'] = 'by Hour'; +$lang->story->report->charts['storysPerOpenedBy'] = 'by CreatedBy'; +$lang->story->report->charts['storysPerAssignedTo'] = 'by Assignee'; +$lang->story->report->charts['storysPerClosedReason'] = 'by Closed Reason'; +$lang->story->report->charts['storysPerChange'] = 'by Change times'; $lang->story->report->options = new stdclass(); $lang->story->report->options->graph = new stdclass(); diff --git a/module/story/lang/zh-cn.php b/module/story/lang/zh-cn.php index 3c328f6cae..6734e32f82 100644 --- a/module/story/lang/zh-cn.php +++ b/module/story/lang/zh-cn.php @@ -114,6 +114,7 @@ $lang->story->stageList['testing'] = '测试中'; $lang->story->stageList['tested'] = '测试完毕'; $lang->story->stageList['verified'] = '已验收'; $lang->story->stageList['released'] = '已发布'; +$lang->story->stageList['closed'] = '已关闭'; $lang->story->reasonList[''] = ''; $lang->story->reasonList['done'] = '已完成'; diff --git a/module/story/lang/zh-tw.php b/module/story/lang/zh-tw.php index e79851cc16..f42730ab48 100644 --- a/module/story/lang/zh-tw.php +++ b/module/story/lang/zh-tw.php @@ -10,7 +10,7 @@ * @link http://www.zentao.net */ $lang->story->create = "提需求"; -$lang->story->batchCreate = "批量添加"; +$lang->story->batchCreate = "批量提需求"; $lang->story->change = "變更"; $lang->story->changed = '需求變更'; $lang->story->review = '評審'; @@ -114,6 +114,7 @@ $lang->story->stageList['testing'] = '測試中'; $lang->story->stageList['tested'] = '測試完畢'; $lang->story->stageList['verified'] = '已驗收'; $lang->story->stageList['released'] = '已發佈'; +$lang->story->stageList['closed'] = '已關閉'; $lang->story->reasonList[''] = ''; $lang->story->reasonList['done'] = '已完成'; diff --git a/module/story/model.php b/module/story/model.php index a6141dd336..3568ffe48b 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -115,10 +115,11 @@ class storyModel extends model /* Get team members. */ if($story->projects) { - $story->teams = $this->dao->select('account, project') + $story->teams = $this->dao->select('account, root') ->from(TABLE_TEAM) - ->where('project')->in(array_keys($story->projects)) - ->fetchGroup('project'); + ->where('root')->in(array_keys($story->projects)) + ->andWhere('type')->eq('project') + ->fetchGroup('root'); } /* Get affected bugs. */ @@ -614,6 +615,7 @@ class storyModel extends model if(!dao::isError()) { + $this->setStage($storyID); if($story->closedReason == 'done') $this->loadModel('score')->create('story', 'close'); $allChanges[$storyID] = common::createChanges($oldStory, $story); } @@ -800,6 +802,7 @@ class storyModel extends model ->add('assignedTo', 'closed') ->add('assignedDate', $now) ->add('status', 'closed') + ->add('stage', 'closed') ->removeIF($this->post->closedReason != 'duplicate', 'duplicateStory') ->removeIF($this->post->closedReason != 'subdivided', 'childStories') ->setIF($this->post->closedReason == 'done', 'stage', 'released') @@ -845,6 +848,7 @@ class storyModel extends model $story->assignedTo = 'closed'; $story->assignedDate = $now; $story->status = 'closed'; + $story->stage = 'closed'; $story->closedReason = $data->closedReasons[$storyID]; $story->duplicateStory = $data->duplicateStoryIDList[$storyID] ? $data->duplicateStoryIDList[$storyID] : $oldStory->duplicateStory; @@ -1310,6 +1314,7 @@ class storyModel extends model * Get stories list of a product. * * @param int $productID + * @param int $branch * @param array|string $moduleIdList * @param string $status * @param string $orderBy @@ -1595,7 +1600,7 @@ class storyModel extends model ->fetchPairs(); $sql = str_replace(array('`product`', '`version`'), array('t1.`product`', 't1.`version`'), $sql); - $tmpStories = $this->dao->select('*')->from(TABLE_STORY)->alias('t1') + $tmpStories = $this->dao->select('t1.*')->from(TABLE_STORY)->alias('t1') ->leftJoin(TABLE_PROJECTSTORY)->alias('t2')->on('t1.id=t2.story') ->where($sql) ->beginIF($productID != 'all' and $productID != '')->andWhere('t1.`product`')->eq((int)$productID)->fi() @@ -1815,7 +1820,7 @@ class storyModel extends model ->andWhere('assignedTo')->eq($account) ->orderBy('id_desc') ->limit($limit) - ->fetchAll(); + ->fetchPairs('id', 'title'); } /** @@ -1833,7 +1838,7 @@ class storyModel extends model ->andWhere('t2.status')->eq('doing') ->andWhere('t2.deleted')->eq(0) ->fetchPairs(); - if($projects) return($this->dao->select('account')->from(TABLE_TEAM)->where('project')->in($projects)->fetchPairs('account')); + if($projects) return($this->dao->select('account')->from(TABLE_TEAM)->where('root')->in($projects)->andWhere('type')->eq('project')->fetchPairs('account')); } /** @@ -2271,8 +2276,10 @@ class storyModel extends model /** * Merge plan title. * - * @param int|array $productID - * @param array $stories + * @param int|array $productID + * @param array $stories + * @param int $branch + * * @access public * @return array */ @@ -2287,13 +2294,9 @@ class storyModel extends model } $plans = $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN) ->where('product')->in($productID) - ->beginIF($branch)->andWhere('branch')->in($branch)->fi() ->andWhere('deleted')->eq(0) ->fetchPairs('id', 'title'); - $stages = $this->dao->select('*')->from(TABLE_STORYSTAGE)->where('branch')->in($branch)->fetchGroup('story', 'branch'); - $branch = trim(str_replace(',0,', '', ",$branch,"), ','); - $branch = empty($branch) ? 0 : $branch; foreach($stories as $story) { $story->planTitle = ''; @@ -2352,15 +2355,15 @@ class storyModel extends model echo ""; break; case 'title': - if($story->branch) echo "{$branches[$story->branch]} "; - if($modulePairs and $story->module) echo "{$modulePairs[$story->module]} "; + if($story->branch and isset($branches[$story->branch])) echo "{$branches[$story->branch]} "; + if($story->module and isset($modulePairs[$story->module])) echo "{$modulePairs[$story->module]} "; echo $canView ? html::a($storyLink, $story->title, '', "style='color: $story->color'") : "{$story->title}"; break; case 'plan': echo $story->planTitle; break; case 'branch': - echo $branches[$story->branch]; + echo zget($branches, $story->branch, ''); break; case 'keywords': echo $story->keywords; @@ -2504,9 +2507,8 @@ class storyModel extends model public function sendmail($storyID, $actionID) { $this->loadModel('mail'); - $story = $this->getById($storyID); - $productName = $this->loadModel('product')->getById($story->product)->name; - $users = $this->loadModel('user')->getPairs('noletter'); + $story = $this->getById($storyID); + $users = $this->loadModel('user')->getPairs('noletter'); /* Get actions. */ $action = $this->loadModel('action')->getById($actionID); @@ -2541,14 +2543,47 @@ class storyModel extends model ob_end_clean(); chdir($oldcwd); + $sendUsers = $this->getToAndCcList($story, $action->action); + if(!$sendUsers) return; + list($toList, $ccList) = $sendUsers; + $subject = $this->getSubject($story); + + /* Send it. */ + $this->mail->send($toList, $subject, $mailContent, $ccList); + if($this->mail->isError()) trigger_error(join("\n", $this->mail->getError())); + } + + /** + * Get mail subject. + * + * @param object $story + * @access public + * @return string + */ + public function getSubject($story) + { + $productName = $this->loadModel('product')->getById($story->product)->name; + return 'STORY #' . $story->id . ' ' . $story->title . ' - ' . $productName; + } + + /** + * Get toList and ccList. + * + * @param object $story + * @param string $actionType + * @access public + * @return bool|array + */ + public function getToAndCcList($story, $actionType) + { /* Set toList and ccList. */ $toList = $story->assignedTo; $ccList = str_replace(' ', '', trim($story->mailto, ',')); /* If the action is changed or reviewed, mail to the project team. */ - if(strtolower($action->action) == 'changed' or strtolower($action->action) == 'reviewed') + if(strtolower($actionType) == 'changed' or strtolower($actionType) == 'reviewed') { - $prjMembers = $this->getProjectMembers($storyID); + $prjMembers = $this->getProjectMembers($story->id); if($prjMembers) { $ccList .= ',' . join(',', $prjMembers); @@ -2558,7 +2593,7 @@ class storyModel extends model if(empty($toList)) { - if(empty($ccList)) return; + if(empty($ccList)) return false; if(strpos($ccList, ',') === false) { $toList = $ccList; @@ -2576,8 +2611,6 @@ class storyModel extends model $toList = $story->openedBy; } - /* Send it. */ - $this->mail->send($toList, 'STORY #' . $story->id . ' ' . $story->title . ' - ' . $productName, $mailContent, $ccList); - if($this->mail->isError()) trigger_error(join("\n", $this->mail->getError())); + return array($toList, $ccList); } } diff --git a/module/story/view/batchcreate.html.php b/module/story/view/batchcreate.html.php index 186532129f..a5a3c327ba 100644 --- a/module/story/view/batchcreate.html.php +++ b/module/story/view/batchcreate.html.php @@ -40,7 +40,7 @@ if($this->story->checkForceReview()) unset($visibleFields['review']); idAB;?> '>product->branch;?> - '>story->module;?> + story->module;?> '>story->plan;?> = 9) echo "class='w-150px'"?>>story->title;?> '>story->spec;?> @@ -93,7 +93,7 @@ if($this->story->checkForceReview()) unset($visibleFields['review']); - '> + ' style='overflow:visible'> ' style='overflow:visible'> ' style='overflow:visible'> @@ -121,7 +121,7 @@ if($this->story->checkForceReview()) unset($visibleFields['review']); %s - '> + ' style='overflow:visible'> ' style='overflow:visible'> ' style='overflow:visible'> diff --git a/module/story/view/batchedit.html.php b/module/story/view/batchedit.html.php index 0302921c71..427dd46b61 100644 --- a/module/story/view/batchedit.html.php +++ b/module/story/view/batchedit.html.php @@ -42,7 +42,7 @@ foreach(explode(',', $showFields) as $field) '>story->branch;?> - '>story->module;?> + story->module;?> '>story->planAB;?> story->title;?> '> story->estimateAB;?> @@ -87,8 +87,12 @@ foreach(explode(',', $showFields) as $field) branch, "class='form-control chosen' onchange='loadBranches($branchProductID, this.value, $storyID);' $disabled");?> - ' style='overflow:visible'> module, "class='form-control chosen'");?> - ' style='overflow:visible'> plan, "class='form-control chosen'");?> + ' style='overflow:visible'> + module, "class='form-control chosen'");?> + + ' style='overflow:visible'> + plan, "class='form-control chosen'");?> +
    color, "data-provide='colorpicker' data-wrapper='input-group-btn fix-border-right' data-pull-menu-right='false' data-btn-tip='{$lang->story->colorTag}' data-update-text='#titles\\[{$storyID}\\]'");?> diff --git a/module/story/view/create.html.php b/module/story/view/create.html.php index a114a8a932..eb9e3f3a9e 100644 --- a/module/story/view/create.html.php +++ b/module/story/view/create.html.php @@ -71,9 +71,9 @@
    story->source?> - story->sourceList, $source, "class='form-control'");?> + story->sourceList, $source, "class='form-control chosen'");?> story->sourceNote?> - +
    @@ -113,7 +113,7 @@ $hasCustomPri = false; foreach($lang->story->priList as $priKey => $priValue) { - if($priKey != $priValue) + if($priKey != $priValue or strlen($priKey) != strlen($priValue)) { $hasCustomPri = true; break; @@ -121,7 +121,7 @@ } ?> - story->priList, $pri, "class='form-control minw-80px'");?> + story->priList, $pri, "class='form-control minw-80px chosen'");?> +
    +
    + +
    + desc), "rows='8' class='form-control'");?> +
    +
    +
    + +
    + todo->statusList, $todo->status, "class='form-control chosen'");?> +
    +
    +
    + +
    + begin, 'onchange=selectNext(); class="form-control chosen"')?> +
    +
    + end, 'class="form-control chosen"');?> +
    +
    + begin == 2400) echo 'checked';?> > + +
    +
    +
    + +
    + private) echo 'checked';?> /> + +
    +
    +
    +
    + + +
    +
    + diff --git a/module/todo/view/view.html.php b/module/todo/view/view.html.php index 5a9138e896..4ff5808fc0 100644 --- a/module/todo/view/view.html.php +++ b/module/todo/view/view.html.php @@ -11,6 +11,7 @@ */ ?> + private or ($todo->private and $todo->account == $app->user->account)):?>
    @@ -24,7 +25,7 @@
    - todo->desc; if($todo->type == 'bug') echo html::a($this->createLink('bug', 'view', "id={$todo->idvalue}"), ' BUG#' . $todo->idvalue); if($todo->type == 'task') echo html::a($this->createLink('task', 'view', "id={$todo->idvalue}"), ' TASK#' . $todo->idvalue); @@ -39,8 +40,8 @@
    - todo->legendBasic;?> - + todo->legendBasic;?> +
    @@ -55,7 +56,7 @@ - + @@ -65,12 +66,66 @@ + assignedTo)):?> + + + + + + + + +
    todo->pri;?> todo->priList[$todo->pri];?>
    todo->account;?>account;?>account);?>
    todo->date;?>todo->beginAndEnd;?> begin])) echo $times[$todo->begin]; if(isset($times[$todo->end])) echo ' ~ ' . $times[$todo->end];?>
    todo->assignTo;?>assignedTo;?>
    todo->assignTo . $lang->todo->date;?>assignedDate;?>
    +
    + cycle):?> + config = json_decode($todo->config);?> +
    + todo->cycle;?> + + + + + + + + + +
    todo->beginAndEnd?>config->begin . " ~ " . $todo->config->end;?>
    todo->cycleConfig?> + config->type == 'day') + { + echo $lang->todo->every . $todo->config->day . $lang->day; + } + elseif($todo->config->type == 'week') + { + foreach(explode(',', $todo->config->week) as $week) echo $lang->todo->dayNames[$week] . ' '; + } + elseif($todo->config->type == 'month') + { + foreach(explode(',', $todo->config->month) as $month) echo $month . ' '; + } + echo '
    '; + if($todo->config->beforeDays) printf($lang->todo->lblBeforeDays, $todo->config->beforeDays); + ?> +
    +
    +
    +
    + comment;?> +
    id")?>' target='hiddenwin'> +
    + +
    +
    + + +id);?> todo->thisIsPrivate;?> diff --git a/module/tree/control.php b/module/tree/control.php index 8be48097e6..02542e5fbe 100644 --- a/module/tree/control.php +++ b/module/tree/control.php @@ -326,9 +326,11 @@ class tree extends control * AJAX: Get the option menu of modules. * * @param int $rootID - * @param string $viewType - * @param int $rootModuleID + * @param string $viewType + * @param int $branch + * @param int $rootModuleID * @param string $returnType + * @param string $fieldID * @param bool $needManage * @access public * @return string the html select string. diff --git a/module/tree/lang/en.php b/module/tree/lang/en.php index 260c70104a..ea236ec550 100644 --- a/module/tree/lang/en.php +++ b/module/tree/lang/en.php @@ -13,21 +13,21 @@ $lang->tree = new stdclass(); $lang->tree->common = 'Module'; $lang->tree->edit = 'Edit'; $lang->tree->delete = 'Delete'; -$lang->tree->browse = 'General Module'; -$lang->tree->browseTask = 'Task Module'; -$lang->tree->manage = 'Manage Module'; +$lang->tree->browse = 'Manage General Module'; +$lang->tree->browseTask = 'Manage Task Module'; +$lang->tree->manage = 'Manage module'; $lang->tree->fix = 'Fix'; $lang->tree->manageProduct = "Manage {$lang->productCommon}"; $lang->tree->manageProject = "Manage {$lang->projectCommon}"; -$lang->tree->manageLine = 'Manage Product Line'; +$lang->tree->manageLine = 'Manage product line'; $lang->tree->manageBug = 'Manage Bug'; $lang->tree->manageCase = 'Manage Case'; $lang->tree->manageCaseLib = 'Manage Library'; $lang->tree->manageCustomDoc = 'Manage DocLib'; -$lang->tree->updateOrder = 'Update Order'; +$lang->tree->updateOrder = 'Sort'; $lang->tree->manageChild = 'Manage Child Module'; -$lang->tree->manageStoryChild = 'Manage Child Story'; -$lang->tree->manageLineChild = 'Manage Product Line'; +$lang->tree->manageStoryChild = 'Manage Child Module'; +$lang->tree->manageLineChild = 'Manage product line'; $lang->tree->manageBugChild = 'Manage Child Bug'; $lang->tree->manageCaseChild = 'Manage Child Case'; $lang->tree->manageCaselibChild = 'Manage Child Library'; diff --git a/module/tree/lang/zh-tw.php b/module/tree/lang/zh-tw.php index 6d0956dab7..fc16aa1637 100644 --- a/module/tree/lang/zh-tw.php +++ b/module/tree/lang/zh-tw.php @@ -45,6 +45,7 @@ $lang->tree->repeatName = '模組名“%s”已經存在!'; $lang->tree->name = '模組名稱'; $lang->tree->line = '產品綫名稱'; +$lang->tree->cate = '分類名稱'; $lang->tree->root = '所屬根'; $lang->tree->branch = '平台/分支'; $lang->tree->path = '路徑'; diff --git a/module/tree/model.php b/module/tree/model.php index 3154bb34ad..5971b0c427 100644 --- a/module/tree/model.php +++ b/module/tree/model.php @@ -372,7 +372,7 @@ class treeModel extends model } if(!$firstBranch) $lastMenu .= ''; - $lastMenu = "
      $lastMenu
    \n"; + $lastMenu = "
      $lastMenu
    \n"; return $lastMenu; } @@ -402,7 +402,7 @@ class treeModel extends model } /* createdVersion > 4.1. */ - $menu = "
      "; + $menu = "
        "; /* Set the start module. */ $startModulePath = ''; @@ -511,8 +511,8 @@ class treeModel extends model { $productInfo = $this->product->getById($id); /* tree menu. */ - $productTree = ''; - $branchTrees = ''; + $productTree = array(); + $branchTrees = array(); if(empty($branchGroups[$id])) $branchGroups[$id]['0'] = ''; foreach($branchGroups[$id] as $branch => $branchName) { @@ -566,7 +566,7 @@ class treeModel extends model public function getProjectStoryTreeMenu($rootID, $startModule = 0, $userFunc) { $extra['projectID'] = $rootID; - $menu = "
          "; + $menu = "
            "; $startModulePath = ''; if($startModule > 0) { @@ -1477,7 +1477,7 @@ class treeModel extends model if(empty($branches)) $branches = $this->post->branch; $branches = array_unique($branches); - if($this->isMergeModule($rootID, $viewType)) $viewType .= ',story'; + if($this->isMergeModule($rootID, $viewType) and $viewType != 'task') $viewType .= ',story'; $existsModules = $this->dao->select('id,branch,name')->from(TABLE_MODULE)->where('root')->eq($rootID)->andWhere('type')->in($viewType)->andWhere('parent')->eq($parentModuleID)->andWhere('branch')->in($branches)->andWhere('deleted')->eq(0)->fetchAll(); $repeatName = ''; diff --git a/module/tree/view/browse.html.php b/module/tree/view/browse.html.php index 64118b6abc..c11daffb87 100644 --- a/module/tree/view/browse.html.php +++ b/module/tree/view/browse.html.php @@ -23,7 +23,7 @@
            -
              +
        @@ -138,7 +138,6 @@ $(function() { var data = $.parseJSON(''); var options = { - name: 'tree--edit', initialState: 'preserve', data: data, sortable: { diff --git a/module/tree/view/browsetask.html.php b/module/tree/view/browsetask.html.php index fccf7fc470..538160f73a 100644 --- a/module/tree/view/browsetask.html.php +++ b/module/tree/view/browsetask.html.php @@ -19,7 +19,7 @@
        -
          +
            @@ -121,14 +121,11 @@ $(function() { var data = $.parseJSON(''); var options = { - name: 'tree-project-edit', initialState: 'preserve', data: data, itemCreator: function($li, item) { - var $toggle = $('' + link + ''); - var title = (item.type === 'product' ? ' ' : '') + item.name; var link = item.id !== undefined ? ('' + title + '') : ('' + title + ''); diff --git a/module/tutorial/lang/en.php b/module/tutorial/lang/en.php index daa70b72af..670abf9b2b 100644 --- a/module/tutorial/lang/en.php +++ b/module/tutorial/lang/en.php @@ -29,7 +29,7 @@ $lang->tutorial->requiredTip = '【%s】is required.'; $lang->tutorial->congratulateTask = 'Congratulations! You have finished【】!'; $lang->tutorial->serverErrorTip = 'Error!'; $lang->tutorial->ajaxSetError = 'Finished task must be defined. If you want to reset the Task, please set its value as null.'; -$lang->tutorial->novice = "If you use ZenTao for the first time, do you want to start the Tutorial?"; +$lang->tutorial->novice = "For a quick start, let's go through a smart(2min) Tutorial?"; $lang->tutorial->dataNotSave = "Data generated in the Tutorial will not be saved!"; $lang->tutorial->tasks = array(); diff --git a/module/tutorial/lang/zh-tw.php b/module/tutorial/lang/zh-tw.php index cd0f0b8303..fffb263c39 100644 --- a/module/tutorial/lang/zh-tw.php +++ b/module/tutorial/lang/zh-tw.php @@ -39,7 +39,7 @@ $lang->tutorial->tasks['createAccount']['nav'] = array('module' => 'user', 'met $lang->tutorial->tasks['createAccount']['desc'] = "

            在系統創建一個新的用戶帳號:

            • 打開 組織 用戶 添加用戶 頁面;
            • 在添加用戶表單中填寫新用戶信息;
            • 保存用戶信息。
            "; $lang->tutorial->tasks['createProduct'] = array('title' => '創建產品'); -$lang->tutorial->tasks['createProduct']['nav'] = array('module' => 'product', 'method' => 'create', 'menu' => 'create', 'form' => '#dataform', 'submit' => '#submit', 'targetPageName' => '新增產品'); +$lang->tutorial->tasks['createProduct']['nav'] = array('module' => 'product', 'method' => 'create', 'menu' => 'create', 'form' => '#dataform', 'submit' => '#submit', 'targetPageName' => '添加產品'); $lang->tutorial->tasks['createProduct']['desc'] = "

            在系統創建一個新的產品:

            • 打開 產品 添加產品 頁面;
            • 在表單中填寫要創建的產品信息;
            • 保存產品信息。
            "; $lang->tutorial->tasks['createStory'] = array('title' => '創建需求'); diff --git a/module/tutorial/model.php b/module/tutorial/model.php index dc5ca1866e..72464b3f55 100644 --- a/module/tutorial/model.php +++ b/module/tutorial/model.php @@ -242,4 +242,15 @@ class tutorialModel extends model $users['test'] = 'Test'; return $users; } + + /** + * Get tutorialed. + * + * @access public + * @return string + */ + public function getTutorialed() + { + return $this->dao->select('*')->from(TABLE_CONFIG)->where('module')->eq('tutorial')->andWhere('owner')->eq($this->app->user->account)->andWhere('section')->eq('tasks')->andWhere('`key`')->eq('setting')->fetch('value'); + } } diff --git a/module/upgrade/control.php b/module/upgrade/control.php index 8052d9b7bf..44a1bf707c 100644 --- a/module/upgrade/control.php +++ b/module/upgrade/control.php @@ -37,8 +37,15 @@ class upgrade extends control { if($this->get->agree == true) $this->locate(inlink('backup')); + $clientLang = $this->app->getClientLang(); + $licenseCN = file_get_contents($this->app->getBasePath() . 'doc/LICENSE.CN'); + $licenseEN = file_get_contents($this->app->getBasePath() . 'doc/LICENSE.EN'); + + $license = $licenseEN . $licenseCN; + if($clientLang == 'zh-cn' or $clientLang == 'zh-tw') $license = $licenseCN . $licenseEN; + $this->view->title = $this->lang->upgrade->common; - $this->view->license = file_get_contents($this->app->getBasePath() . 'doc/LICENSE'); + $this->view->license = $license; $this->display(); } diff --git a/module/upgrade/css/afterexec.css b/module/upgrade/css/afterexec.css index 3151ee49a3..8d820e952d 100644 --- a/module/upgrade/css/afterexec.css +++ b/module/upgrade/css/afterexec.css @@ -1,19 +1,10 @@ .adbox{margin-top:20px;} -.card { - border: none; - border-radius: 0px; - box-shadow: none; - display: block; - margin-bottom: 0px; - overflow: hidden; - padding: 0; - position: relative; - transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1) 0s; -} + +.card.ad{margin-bottom:0px;} .card.ad > .img-wrapper { background-position: center; background-repeat: no-repeat; - height: 85px; + height: 115px; width: 100%; } .card.ad > .img-wrapper > img{display: none;} diff --git a/module/upgrade/lang/en.php b/module/upgrade/lang/en.php index 84a645e2f5..453e8d88c9 100644 --- a/module/upgrade/lang/en.php +++ b/module/upgrade/lang/en.php @@ -129,3 +129,7 @@ $lang->upgrade->fromVersions['9_5_1'] = '9.5.1'; $lang->upgrade->fromVersions['9_6'] = '9.6'; $lang->upgrade->fromVersions['9_6_1'] = '9.6.1'; $lang->upgrade->fromVersions['9_6_2'] = '9.6.2'; +$lang->upgrade->fromVersions['9_6_3'] = '9.6.3'; +$lang->upgrade->fromVersions['9_7'] = '9.7'; +$lang->upgrade->fromVersions['9_8'] = '9.8'; +$lang->upgrade->fromVersions['9_8_1'] = '9.8.1'; diff --git a/module/upgrade/lang/zh-cn.php b/module/upgrade/lang/zh-cn.php index cfbc9a4ab8..5cb4fe1699 100644 --- a/module/upgrade/lang/zh-cn.php +++ b/module/upgrade/lang/zh-cn.php @@ -129,3 +129,7 @@ $lang->upgrade->fromVersions['9_5_1'] = '9.5.1'; $lang->upgrade->fromVersions['9_6'] = '9.6'; $lang->upgrade->fromVersions['9_6_1'] = '9.6.1'; $lang->upgrade->fromVersions['9_6_2'] = '9.6.2'; +$lang->upgrade->fromVersions['9_6_3'] = '9.6.3'; +$lang->upgrade->fromVersions['9_7'] = '9.7'; +$lang->upgrade->fromVersions['9_8'] = '9.8'; +$lang->upgrade->fromVersions['9_8_1'] = '9.8.1'; diff --git a/module/upgrade/lang/zh-tw.php b/module/upgrade/lang/zh-tw.php index 7da01c03ea..591ec9d8a8 100644 --- a/module/upgrade/lang/zh-tw.php +++ b/module/upgrade/lang/zh-tw.php @@ -129,3 +129,7 @@ $lang->upgrade->fromVersions['9_5_1'] = '9.5.1'; $lang->upgrade->fromVersions['9_6'] = '9.6'; $lang->upgrade->fromVersions['9_6_1'] = '9.6.1'; $lang->upgrade->fromVersions['9_6_2'] = '9.6.2'; +$lang->upgrade->fromVersions['9_6_3'] = '9.6.3'; +$lang->upgrade->fromVersions['9_7'] = '9.7'; +$lang->upgrade->fromVersions['9_8'] = '9.8'; +$lang->upgrade->fromVersions['9_8_1'] = '9.8.1'; diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 6ea04e8f06..7803f4007a 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -75,13 +75,13 @@ class upgradeModel extends model $this->execSQL($this->getUpgradeFile('3.3')); $this->updateTaskAssignedTo(); case '4_0_beta1': $this->execSQL($this->getUpgradeFile('4.0.beta1')); - case '4_0_beta2': + case '4_0_beta2': $this->execSQL($this->getUpgradeFile('4.0.beta2')); $this->updateProjectType(); $this->updateEstimatePriv(); - case '4_0': + case '4_0': $this->execSQL($this->getUpgradeFile('4.0')); - case '4_0_1': + case '4_0_1': $this->execSQL($this->getUpgradeFile('4.0.1')); $this->addPriv4_0_1(); case '4_1': @@ -195,15 +195,28 @@ class upgradeModel extends model $this->fixDatatableColsConfig(); case '9_6_1': $this->addLimitedGroup(); - } + case '9_6_2': + case '9_6_3': + $this->execSQL($this->getUpgradeFile('9.6.3')); + $this->changeLimitedName(); + $this->adjustPriv9_7(); + $this->changeStoryWidth(); + case '9_7': + $this->execSQL($this->getUpgradeFile('9.7')); + $this->changeTeamFields(); + $this->moveData2Notify(); + case '9_8': + $this->fixFinishedBy(); + case '9_8_1': + } $this->deletePatch(); } /** * Create the confirm contents. - * - * @param string $fromVersion + * + * @param string $fromVersion * @access public * @return string */ @@ -269,7 +282,7 @@ class upgradeModel extends model case '8_0_1': $confirmContent .= file_get_contents($this->getUpgradeFile('8.0.1')); case '8_1': $confirmContent .= file_get_contents($this->getUpgradeFile('8.1')); case '8_1_3': $confirmContent .= file_get_contents($this->getUpgradeFile('8.1.3')); - case '8_2_beta': + case '8_2_beta': case '8_2': case '8_2_1': $confirmContent .= file_get_contents($this->getUpgradeFile('8.2.1')); case '8_2_2': @@ -294,6 +307,12 @@ class upgradeModel extends model case '9_5': $confirmContent .= file_get_contents($this->getUpgradeFile('9.5')); case '9_5_1': $confirmContent .= file_get_contents($this->getUpgradeFile('9.5.1')); case '9_6': $confirmContent .= file_get_contents($this->getUpgradeFile('9.6')); + case '9_6_1': + case '9_6_2': + case '9_6_3': $confirmContent .= file_get_contents($this->getUpgradeFile('9.6.3')); + case '9_7': $confirmContent .= file_get_contents($this->getUpgradeFile('9.7')); + case '9_8': + case '9_8_1': } return str_replace('zt_', $this->config->db->prefix, $confirmContent); } @@ -329,7 +348,7 @@ class upgradeModel extends model /** * Update ubb code in bug table and user Templates table to html. - * + * * @access public * @return void */ @@ -391,7 +410,7 @@ class upgradeModel extends model /** * Update nl to br from 1.3 version. - * + * * @access public * @return void */ @@ -437,7 +456,7 @@ class upgradeModel extends model /** * Update task fields. - * + * * @access public * @return void */ @@ -519,8 +538,8 @@ class upgradeModel extends model } /** - * Update activated count of Bug. - * + * Update activated count of Bug. + * * @access public * @return void */ @@ -543,7 +562,7 @@ class upgradeModel extends model /** * Update lastRun and lastResult field in zt_case - * + * * @access public * @return void */ @@ -561,21 +580,21 @@ class upgradeModel extends model } /** - * Update type of projects. - * + * Update type of projects. + * * @access public * @return void */ public function updateProjectType() { - $projects = $this->dao->select('root')->from(TABLE_MODULE)->where('type')->eq('task')->fetchPairs('root'); - $this->dao->update(TABLE_PROJECT)->set('type')->eq('waterfall')->where('id')->in($projects)->exec(); + $projects = $this->dao->select('root')->from(TABLE_MODULE)->where('type')->eq('task')->fetchPairs('root'); + $this->dao->update(TABLE_PROJECT)->set('type')->eq('waterfall')->where('id')->in($projects)->exec(); return true; } /** * Update estimate priv. - * + * * @access public * @return void */ @@ -628,8 +647,8 @@ class upgradeModel extends model } /** - * Update the data of action. - * + * Update the data of action. + * * @access public * @return void */ @@ -673,8 +692,8 @@ class upgradeModel extends model } /** - * Init the data of product and project order field. - * + * Init the data of product and project order field. + * * @access public * @return void */ @@ -695,7 +714,7 @@ class upgradeModel extends model /** * Update task assignedTo. - * + * * @access public * @return void */ @@ -710,7 +729,7 @@ class upgradeModel extends model /** * Delete the patch record. - * + * * @access public * @return void */ @@ -722,8 +741,8 @@ class upgradeModel extends model /** * Get the upgrade sql file. - * - * @param string $version + * + * @param string $version * @access public * @return string */ @@ -734,8 +753,8 @@ class upgradeModel extends model /** * Execute a sql. - * - * @param string $sqlFile + * + * @param string $sqlFile * @access public * @return void */ @@ -746,7 +765,7 @@ class upgradeModel extends model /* Read the sql file to lines, remove the comment lines, then join theme by ';'. */ $sqls = explode("\n", file_get_contents($sqlFile)); - foreach($sqls as $key => $line) + foreach($sqls as $key => $line) { $line = trim($line); $sqls[$key] = $line; @@ -771,7 +790,7 @@ class upgradeModel extends model { $this->dbh->exec($sql); } - catch (PDOException $e) + catch (PDOException $e) { $errorInfo = $e->errorInfo; $errorCode = $errorInfo[1]; @@ -781,8 +800,8 @@ class upgradeModel extends model } /** - * Add priv for version 4.0.1 - * + * Add priv for version 4.0.1 + * * @access public * @return void */ @@ -823,10 +842,10 @@ class upgradeModel extends model } /** - * Add priv for version 4.1 - * + * Add priv for version 4.1 + * * @access public - * @return bool + * @return bool */ public function addPriv4_1() { @@ -918,7 +937,7 @@ class upgradeModel extends model /** * Add priv for 8.2. - * + * * @access public * @return bool */ @@ -964,7 +983,7 @@ class upgradeModel extends model /** * Adjust config section and key. - * + * * @access public * @return bool */ @@ -983,8 +1002,8 @@ class upgradeModel extends model /** * To lower table. - * - * @param string $build + * + * @param string $build * @access public * @return bool */ @@ -1028,7 +1047,7 @@ class upgradeModel extends model /** * Process finishedBy and finishedDate of task. - * + * * @access public * @return bool */ @@ -1046,7 +1065,7 @@ class upgradeModel extends model /** * Delete company field for the table of zt_config and zt_groupPriv. - * + * * @access public * @return void */ @@ -1080,7 +1099,7 @@ class upgradeModel extends model /** * Merge the goal and desc of project. - * + * * @access public * @return void */ @@ -1101,7 +1120,7 @@ class upgradeModel extends model /** * Fix OS info of bugs. - * + * * @access public * @return void */ @@ -1113,7 +1132,7 @@ class upgradeModel extends model /** * Fix finishedBy of task. - * + * * @access public * @return void */ @@ -1143,7 +1162,7 @@ class upgradeModel extends model /** * Touch index.html for upload when has not it. - * + * * @access public * @return bool */ @@ -1159,7 +1178,7 @@ class upgradeModel extends model /** * Init order. - * + * * @access public * @return bool */ @@ -1178,7 +1197,7 @@ class upgradeModel extends model /** * Adjust order for 7.3 - * + * * @access public * @return void */ @@ -1191,8 +1210,8 @@ class upgradeModel extends model } /** - * Adjust priv for 7.4.beta - * + * Adjust priv for 7.4.beta + * * @access public * @return void */ @@ -1213,7 +1232,7 @@ class upgradeModel extends model /** * Adjust doc module. - * + * * @access public * @return bool */ @@ -1322,7 +1341,7 @@ class upgradeModel extends model /** * Update file objectID in editor. - * + * * @access public * @return bool */ @@ -1428,7 +1447,7 @@ class upgradeModel extends model /** * Move doc content to table zt_doccontent. - * + * * @access public * @return bool */ @@ -1438,7 +1457,7 @@ class upgradeModel extends model $processFields = 0; foreach($descDoc as $field) { - if($field->Field == 'content' or $field->Field == 'digest' or $field->Field == 'url') $processFields ++; + if($field->Field == 'content' or $field->Field == 'digest' or $field->Field == 'url') $processFields ++; } if($processFields < 3) return true; @@ -1466,8 +1485,8 @@ class upgradeModel extends model } /** - * Adjust priv 8.3 - * + * Adjust priv 8.3 + * * @access public * @return bool */ @@ -1490,10 +1509,10 @@ class upgradeModel extends model } return true; } - + /** * Rename main lib. - * + * * @access public * @return bool */ @@ -1507,7 +1526,7 @@ class upgradeModel extends model /** * Adjust priv for 8.4. - * + * * @access public * @return bool */ @@ -1538,8 +1557,8 @@ class upgradeModel extends model } /** - * Adjust priv for 9.0 - * + * Adjust priv for 9.0 + * * @access public * @return void */ @@ -1568,7 +1587,7 @@ class upgradeModel extends model /** * Fix projectproduct data. - * + * * @access public * @return bool */ @@ -1580,7 +1599,7 @@ class upgradeModel extends model /** * Add bug deadline for custom fields. - * + * * @access public * @return bool */ @@ -1612,8 +1631,8 @@ class upgradeModel extends model } /** - * Adjust priv for 9.0.1. - * + * Adjust priv for 9.0.1. + * * @access public * @return bool */ @@ -1719,7 +1738,7 @@ class upgradeModel extends model * Adjust priv for 9.4. * * @access public - * @return bool + * @return bool */ public function adjustPriv9_4() { @@ -1730,6 +1749,7 @@ class upgradeModel extends model $data->group = $groupID; $data->module = 'bug'; $data->method = 'batchActivate'; + $this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec(); } return true; } @@ -1747,7 +1767,7 @@ class upgradeModel extends model /** * Get errors during the upgrading. - * + * * @access public * @return array */ @@ -1760,7 +1780,7 @@ class upgradeModel extends model /** * Check safe file. - * + * * @access public * @return string|false */ @@ -1773,7 +1793,7 @@ class upgradeModel extends model /** * Check weither process or not. - * + * * @access public * @return array */ @@ -1786,8 +1806,8 @@ class upgradeModel extends model } /** - * Process customMenus for different working. - * + * Process customMenus for different working. + * * @access public * @return void */ @@ -1806,7 +1826,7 @@ class upgradeModel extends model /** * Init project story order. - * + * * @access public * @return bool */ @@ -1831,7 +1851,7 @@ class upgradeModel extends model /** * Fix datatable cols config. - * + * * @access public * @return bool */ @@ -1859,7 +1879,7 @@ class upgradeModel extends model /** * Add limited group. - * + * * @access public * @return bool */ @@ -1904,7 +1924,7 @@ class upgradeModel extends model /** * Change limited name. - * + * * @access public * @return bool */ @@ -1920,8 +1940,8 @@ class upgradeModel extends model } /** - * Adjust Priv for 9.7 - * + * Adjust Priv for 9.7 + * * @access public * @return bool */ @@ -1941,7 +1961,7 @@ class upgradeModel extends model /** * Change story field width. - * + * * @access public * @return bool */ @@ -1959,4 +1979,136 @@ class upgradeModel extends model } return true; } + + /** + * Change team field for 9.8. + * + * @access public + * @return bool + */ + public function changeTeamFields() + { + $desc = $this->dao->query('DESC ' . TABLE_TEAM)->fetchAll(); + $fields = array(); + foreach($desc as $field) + { + $fieldName = $field->Field; + $fields[$fieldName] = $fieldName; + } + if(isset($fields['root'])) return true; + + $this->dao->exec("ALTER TABLE " . TABLE_TEAM . " CHANGE `project` `root` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0'"); + $this->dao->exec("ALTER TABLE " . TABLE_TEAM . " ADD `type` ENUM('project', 'task') NOT NULL DEFAULT 'project' AFTER `root`"); + $this->dao->exec("UPDATE " . TABLE_TEAM . " SET `root` = `task`, `type` = 'task' WHERE `task` > '0'"); + $this->dao->exec("ALTER TABLE " . TABLE_TEAM . " DROP PRIMARY KEY"); + $this->dao->exec("ALTER TABLE " . TABLE_TEAM . " DROP `task`"); + return true; + } + + /** + * Move data to notify. + * + * @access public + * @return bool + */ + public function moveData2Notify() + { + $this->dao->exec('TRUNCATE TABLE ' . TABLE_NOTIFY); + $mailQueueTable = '`' . $this->config->db->prefix . 'mailqueue`'; + $stmt = $this->dao->select('*')->from($mailQueueTable)->query(); + while($mailQueue = $stmt->fetch()) + { + $notify = new stdclass(); + $notify->objectType = 'mail'; + $notify->toList = $mailQueue->toList; + $notify->ccList = $mailQueue->ccList; + $notify->subject = $mailQueue->subject; + $notify->data = $mailQueue->body; + $notify->createdBy = $mailQueue->addedBy; + $notify->createdDate = $mailQueue->addedDate; + $notify->sendTime = $mailQueue->sendTime; + $notify->status = $mailQueue->status; + $notify->failReason = $mailQueue->failReason; + $this->dao->insert(TABLE_NOTIFY)->data($notify)->exec(); + } + + $webhookDataTable = '`' . $this->config->db->prefix . 'webhookdatas`'; + $stmt = $this->dao->select('*')->from($webhookDataTable)->query(); + while($webhookData = $stmt->fetch()) + { + $notify = new stdclass(); + $notify->objectType = 'webhook'; + $notify->objectID = $webhookData->webhook; + $notify->action = $webhookData->action; + $notify->data = $webhookData->data; + $notify->createdBy = $webhookData->createdBy; + $notify->createdDate = $webhookData->createdDate; + $notify->status = $webhookData->status; + $this->dao->insert(TABLE_NOTIFY)->data($notify)->exec(); + } + return true; + } + + /** + * Adjust priv 9.8. + * + * @access public + * @return bool + */ + public function adjustPriv9_8() + { + $groups = $this->dao->select('id')->from(TABLE_GROUP)->fetchPairs('id', 'id'); + foreach($groups as $group) + { + $groupPriv = new stdclass(); + $groupPriv->group = $groupID; + $groupPriv->module = 'todo'; + $groupPriv->method = 'createcycle'; + $this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec(); + } + + $groups = $this->dao->select('*')->from(TABLE_GROUPPRIV)->where('module')->eq('mail')->orWhere('module')->eq('webhook')->fetchPairs('group', 'group'); + foreach($groups as $group) + { + $groupPriv = new stdclass(); + $groupPriv->group = $groupID; + $groupPriv->module = 'message'; + $groupPriv->method = 'index'; + $this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec(); + } + + $groups = $this->dao->select('*')->from(TABLE_GROUPPRIV)->where('module')->eq('project')->andWhere('method')->eq('linkStory')->fetchPairs('group', 'group'); + foreach($groups as $group) + { + $groupPriv = new stdclass(); + $groupPriv->group = $groupID; + $groupPriv->module = 'project'; + $groupPriv->method = 'importPlanStories'; + $this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec(); + } + return true; + } + + /** + * Fix task finishedBy. + * + * @access public + * @return bool + */ + public function fixFinishedBy() + { + $stmt = $this->dao->select('t1.id as historID,t2.objectType,t2.objectID,t2.actor')->from(TABLE_HISTORY)->alias('t1') + ->leftJoin(TABLE_ACTION)->alias('t2')->on('t1.action=t2.id') + ->where('t1.field')->eq('finishedBy') + ->andWhere('t2.objectType')->eq('task') + ->andWhere('t2.action')->eq('finished') + ->andWhere('t2.actor != t1.`new`') + ->query(); + while($action = $stmt->fetch()) + { + $this->dao->update(TABLE_HISTORY)->set('`new`')->eq($action->actor)->where('id')->eq($action->historID)->exec(); + $this->dao->update(TABLE_TASK)->set('`finishedBy`')->eq($action->actor)->where('id')->eq($action->objectID)->exec(); + } + return true; + } } diff --git a/module/upgrade/view/afterexec.html.php b/module/upgrade/view/afterexec.html.php index b2b1d9fc1c..0590377b09 100644 --- a/module/upgrade/view/afterexec.html.php +++ b/module/upgrade/view/afterexec.html.php @@ -22,22 +22,18 @@
            install->promotion?>
            - diff --git a/module/user/config.php b/module/user/config.php index b4211a351f..bd2bfb21c9 100644 --- a/module/user/config.php +++ b/module/user/config.php @@ -6,8 +6,8 @@ $config->user->edit = new stdclass(); $config->user->create->requiredFields = 'account,realname,password,password1,password2'; $config->user->edit->requiredFields = 'account,realname'; -$config->user->customBatchCreateFields = 'dept,email,gender,commiter,join,skype,qq,yahoo,gtalk,wangwang,mobile,phone,address,zipcode'; -$config->user->customBatchEditFields = 'dept,email,commiter,join,skype,qq,yahoo,gtalk,wangwang,mobile,phone,address,zipcode'; +$config->user->customBatchCreateFields = 'dept,email,gender,commiter,skype,qq,yahoo,gtalk,wangwang,mobile,phone,address,zipcode'; +$config->user->customBatchEditFields = 'dept,email,commiter,skype,qq,yahoo,gtalk,wangwang,mobile,phone,address,zipcode'; $config->user->custom = new stdclass(); $config->user->custom->batchCreateFields = 'dept,email,gender'; diff --git a/module/user/control.php b/module/user/control.php index 2188c95621..bfb38b2fd2 100644 --- a/module/user/control.php +++ b/module/user/control.php @@ -626,31 +626,6 @@ class user extends control } } - /** - * Check Tmp dir. - * - * @access public - * @return void - */ - public function checkTmp() - { - if(!is_dir($this->app->tmpRoot)) mkdir($this->app->tmpRoot, 0755, true); - if(!is_dir($this->app->cacheRoot)) mkdir($this->app->cacheRoot, 0755, true); - if(!is_dir($this->app->logRoot)) mkdir($this->app->logRoot, 0755, true); - if(!is_dir($this->app->logRoot)) return false; - - $file = $this->app->logRoot . DS . 'demo.txt'; - if($fp = @fopen($file, 'a+')) - { - @fclose($fp); - @unlink($file); - } - else - { - return false; - } - return true; - } /** * User login, identify him and authorize him. @@ -663,7 +638,7 @@ class user extends control */ public function login($referer = '', $from = '') { - if($this->checkTmp() === false) + if($this->user->checkTmp() === false) { echo ""; echo "
            "; @@ -736,9 +711,6 @@ class user extends control /* Keep login. */ if($this->post->keepLogin) $this->user->keepLogin($user); - /* Check password. */ - if(isset($this->config->safe->mode) and $this->user->computePasswordStrength($password) < $this->config->safe->mode) echo js::alert($this->lang->user->weakPassword); - /* Go to the referer. */ if($this->post->referer and strpos($this->post->referer, $loginLink) === false and strpos($this->post->referer, $denyLink) === false) { @@ -807,7 +779,9 @@ class user extends control { if(!empty($this->config->global->showDemoUsers)) { - $demoUsers = $this->user->getPairs('noletter|noempty|noclosed|nodeleted'); + $demoUsers = 'productManager,projectManager,dev1,dev2,dev3,tester1,tester2,tester3,testManager'; + if($this->app->getClientLang() == 'en') $demoUsers = 'thePO,pm1,pm2,pg1,pg2,pg3,thePM,qa1,theQS'; + $demoUsers = $this->dao->select('account,password,realname')->from(TABLE_USER)->where('account')->in($demoUsers)->andWhere('deleted')->eq(0)->fetchAll('account'); $this->view->demoUsers = $demoUsers; } diff --git a/module/user/lang/en.php b/module/user/lang/en.php index 6be646a744..5416043108 100644 --- a/module/user/lang/en.php +++ b/module/user/lang/en.php @@ -20,13 +20,13 @@ $lang->user->role = 'Role'; $lang->user->group = 'Group'; $lang->user->realname = 'Name'; $lang->user->nickname = 'Nickname'; -$lang->user->commiter = 'Commiter'; +$lang->user->commiter = 'SCM Account'; $lang->user->birthyear = 'Birth Year'; $lang->user->gender = 'Gender'; $lang->user->email = 'Email'; $lang->user->basicInfo = 'Basic Info'; $lang->user->accountInfo = 'Account'; -$lang->user->verify = 'Acceptance'; +$lang->user->verify = 'Safety Verification'; $lang->user->contactInfo = 'Contact'; $lang->user->skype = 'Skype'; $lang->user->qq = 'QQ'; @@ -44,12 +44,12 @@ $lang->user->last = 'Last Login'; $lang->user->ranzhi = 'Zdoo Account'; $lang->user->ditto = 'Ditto'; $lang->user->originalPassword = 'Old Password'; -$lang->user->verifyPassword = 'Enter your password'; +$lang->user->verifyPassword = 'Admin password'; $lang->user->resetPassword = 'Forgot Password?'; $lang->user->index = "Home"; -$lang->user->view = "Info"; -$lang->user->create = "Add"; +$lang->user->view = "Overview"; +$lang->user->create = "Add User"; $lang->user->batchCreate = "Batch Add User"; $lang->user->edit = "Edit"; $lang->user->batchEdit = "Batch Edit"; @@ -75,7 +75,7 @@ $lang->user->bug = 'Bug'; $lang->user->test = 'Test'; $lang->user->testTask = 'Test Task'; $lang->user->testCase = 'Test Case'; -$lang->user->todo = 'To-Do'; +$lang->user->todo = 'Todo'; $lang->user->story = 'Story'; $lang->user->dynamic = 'Dynamic'; @@ -95,17 +95,24 @@ $lang->user->errorDeny = "Sorry, your access to %s Module %s Fe $lang->user->loginFailed = "Login failed. Please check your account and password."; $lang->user->lockWarning = "You can try %s times."; $lang->user->loginLocked = "Please contact the administrator to unlock your account or try %s mins later."; -$lang->user->weakPassword = "Your password does meet the setting requirements."; +$lang->user->weakPassword = "Your password does not meet the setting requirements."; $lang->user->roleList[''] = ''; $lang->user->roleList['dev'] = 'Developer'; $lang->user->roleList['qa'] = 'QA'; $lang->user->roleList['pm'] = 'Project Manager'; $lang->user->roleList['po'] = 'Product Owner'; +<<<<<<< HEAD $lang->user->roleList['td'] = 'Test Director'; $lang->user->roleList['pd'] = 'Product Director'; $lang->user->roleList['qd'] = 'QA Director'; $lang->user->roleList['top'] = 'Top Manager'; +======= +$lang->user->roleList['td'] = 'Technical Manager'; +$lang->user->roleList['pd'] = 'Product Manager'; +$lang->user->roleList['qd'] = 'QA Manager'; +$lang->user->roleList['top'] = 'Senior Manager'; +>>>>>>> d53267cadf32651eb7ccfff3e0b1a5dd744d3d3e $lang->user->roleList['others'] = 'Other'; $lang->user->genderList['m'] = 'M'; @@ -128,15 +135,15 @@ $lang->user->tpl->content = 'Content'; $lang->user->tpl->public = 'Public'; $lang->user->placeholder = new stdclass(); -$lang->user->placeholder->account = 'letters, underline, and numbers,at lease three characters'; +$lang->user->placeholder->account = 'Letters, Underline and Numbers, at least 3 characters'; $lang->user->placeholder->password1 = 'six characters at lease '; $lang->user->placeholder->role = "Role affects content and user order."; $lang->user->placeholder->group = "Group decides user privilege."; -$lang->user->placeholder->commiter = 'Subversion Account'; +$lang->user->placeholder->commiter = 'Svn or Git like'; $lang->user->placeholder->verify = 'Password is required.'; -$lang->user->placeholder->passwordStrength[1] = 'letters and numbers, at lease six characters'; -$lang->user->placeholder->passwordStrength[2] = 'letters, numbers and special characters, at lease 10 characters'; +$lang->user->placeholder->passwordStrength[1] = 'Letters and Numbers, at least 6 characters'; +$lang->user->placeholder->passwordStrength[2] = 'Letters, Numbers and special characters, at lease 10 characters'; $lang->user->error = new stdclass(); $lang->user->error->account = "ID %s,must be contain letters, underline, and numbers,at lease three characters"; @@ -157,7 +164,7 @@ $lang->user->contacts->userList = 'User List'; $lang->user->contacts->manage = 'Manage'; $lang->user->contacts->contactsList = 'Contacts'; -$lang->user->contacts->selectedUsers = 'User'; +$lang->user->contacts->selectedUsers = 'Select User'; $lang->user->contacts->selectList = 'List'; $lang->user->contacts->createList = 'Create a List'; $lang->user->contacts->noListYet = 'No contact list exists. Please create a list first.'; diff --git a/module/user/lang/zh-tw.php b/module/user/lang/zh-tw.php index a0766cfce1..ea3c98fdef 100644 --- a/module/user/lang/zh-tw.php +++ b/module/user/lang/zh-tw.php @@ -145,6 +145,7 @@ $lang->user->error->realname = "ID %s,必須填寫真實姓名"; $lang->user->error->password = "ID %s,密碼必須六位以上"; $lang->user->error->mail = "ID %s,請填寫正確的郵箱地址"; $lang->user->error->role = "ID %s,職位不能為空"; +$lang->user->error->reserved = "ID %s,該用戶名系統預留"; $lang->user->error->verifyPassword = "安全驗證密碼錯誤,請輸入你的登錄密碼"; $lang->user->error->originalPassword = "原密碼不正確"; diff --git a/module/user/model.php b/module/user/model.php index d124add45d..42335a2b0d 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -15,7 +15,7 @@ class userModel extends model { /** * Set the menu. - * + * * @param array $users user pairs * @param string $account current account * @access public @@ -34,11 +34,11 @@ class userModel extends model /** * Set users list. - * - * @param array $users - * @param string $account + * + * @param array $users + * @param string $account * @access public - * @return html + * @return html */ public function setUserList($users, $account) { @@ -52,7 +52,7 @@ class userModel extends model /** * Get users list of current company. - * + * * @access public * @return void */ @@ -112,9 +112,9 @@ class userModel extends model /** * Get commiters from the user table. - * + * * @access public - * @return array + * @return array */ public function getCommiters() { @@ -133,11 +133,11 @@ class userModel extends model return $commiters; } - + /** * Get user list with email and real name. - * - * @param string|array $users + * + * @param string|array $users * @access public * @return array */ @@ -151,8 +151,8 @@ class userModel extends model /** * Get roles for some users. - * - * @param string $users + * + * @param string $users * @access public * @return array */ @@ -167,8 +167,8 @@ class userModel extends model /** * Get user info by ID. - * - * @param int $userID + * + * @param int $userID * @access public * @return object|bool */ @@ -182,9 +182,9 @@ class userModel extends model /** * Get users by sql. - * - * @param int $query - * @param int $pager + * + * @param int $query + * @param int $pager * @access public * @return void */ @@ -213,6 +213,7 @@ class userModel extends model ->setDefault('join', '0000-00-00') ->setIF($this->post->password1 != false, 'password', md5($this->post->password1)) ->setIF($this->post->password1 == false, 'password', '') + ->setIF($this->post->email != false, 'email', trim($this->post->email)) ->remove('group, password1, password2, verifyPassword') ->get(); @@ -233,7 +234,6 @@ class userModel extends model ->batchCheck($this->config->user->create->requiredFields, 'notempty') ->check('account', 'unique') ->check('account', 'account') - ->checkIF($this->post->email != false, 'email', 'email') ->exec(); if($this->post->group) { @@ -287,9 +287,9 @@ class userModel extends model $data[$i]->group = $users->group[$i] == 'ditto' ? (isset($prev['group']) ? $prev['group'] : '') : $users->group[$i]; $data[$i]->email = $users->email[$i]; $data[$i]->gender = $users->gender[$i]; - $data[$i]->password = md5($users->password[$i]); + $data[$i]->password = md5($users->password[$i]); $data[$i]->commiter = $users->commiter[$i]; - $data[$i]->join = empty($users->join[$i]) ? '0000-00-00' : ($user->join[$i]); + $data[$i]->join = empty($users->join[$i]) ? '0000-00-00' : ($users->join[$i]); $data[$i]->skype = $users->skype[$i]; $data[$i]->qq = $users->qq[$i]; $data[$i]->yahoo = $users->yahoo[$i]; @@ -333,7 +333,7 @@ class userModel extends model } unset($user->group); $this->dao->insert(TABLE_USER)->data($user)->autoCheck()->exec(); - if(dao::isError()) + if(dao::isError()) { echo js::error(dao::getError()); die(js::reload('parent')); @@ -347,8 +347,8 @@ class userModel extends model /** * Update a user. - * - * @param int $userID + * + * @param int $userID * @access public * @return void */ @@ -362,6 +362,7 @@ class userModel extends model $user = fixer::input('post') ->setDefault('join', '0000-00-00') ->setIF($this->post->password1 != false, 'password', md5($this->post->password1)) + ->setIF($this->post->email != false, 'email', trim($this->post->email)) ->remove('password1, password2, groups,verifyPassword') ->get(); @@ -382,7 +383,6 @@ class userModel extends model ->batchCheck($this->config->user->edit->requiredFields, 'notempty') ->check('account', 'unique', "id != '$userID'") ->check('account', 'account') - ->checkIF($this->post->email != false, 'email', 'email') ->where('id')->eq((int)$userID) ->exec(); @@ -523,9 +523,9 @@ class userModel extends model } /** - * Update password - * - * @param string $userID + * Update password + * + * @param string $userID * @access public * @return void */ @@ -560,14 +560,14 @@ class userModel extends model /** * Reset password. - * + * * @access public * @return bool */ public function resetPassword() { if(!$this->checkPassword()) return; - + $user = $this->getById($this->post->account); if(!$user) return false; @@ -584,7 +584,7 @@ class userModel extends model /** * Check the passwds posted. - * + * * @access public * @return bool */ @@ -601,7 +601,7 @@ class userModel extends model /** * Identify a user. - * + * * @param string $account the user account * @param string $password the user password or auth hash * @access public @@ -657,13 +657,17 @@ class userModel extends model } $this->dao->update(TABLE_USER)->set('visits = visits + 1')->set('ip')->eq($ip)->set('last')->eq($last)->where('account')->eq($account)->exec(); + + /* Create cycle todo in login. */ + $todoList = $this->dao->select('*')->from(TABLE_TODO)->where('cycle')->eq(1)->andWhere('account')->eq($user->account)->fetchAll('id'); + $this->loadModel('todo')->createByCycle($todoList); } return $user; } /** * Identify user by PHP_AUTH_USER. - * + * * @access public * @return void */ @@ -684,7 +688,7 @@ class userModel extends model /** * Identify user by cookie. - * + * * @access public * @return void */ @@ -707,7 +711,7 @@ class userModel extends model /** * Authorize a user. - * + * * @param string $account * @access public * @return array the user rights. @@ -795,7 +799,7 @@ class userModel extends model /** * Judge a user is logon or not. - * + * * @access public * @return bool */ @@ -806,8 +810,8 @@ class userModel extends model /** * Get groups a user belongs to. - * - * @param string $account + * + * @param string $account * @access public * @return array */ @@ -817,17 +821,18 @@ class userModel extends model } /** - * Get projects a user participated. - * - * @param string $account + * Get projects a user participated. + * + * @param string $account * @access public * @return array */ public function getProjects($account) { $projects = $this->dao->select('t1.*,t2.*')->from(TABLE_TEAM)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.root = t2.id') ->where('t1.account')->eq($account) + ->andWhere('t1.type')->eq('project') ->andWhere('t2.deleted')->eq(0) ->fetchAll(); @@ -846,8 +851,8 @@ class userModel extends model /** * Plus the fail times. - * - * @param int $account + * + * @param int $account * @access public * @return void */ @@ -857,8 +862,8 @@ class userModel extends model if(empty($user)) return 0; $fails = $user->fails; - $fails ++; - if($fails < $this->config->user->failTimes) + $fails ++; + if($fails < $this->config->user->failTimes) { $locked = '0000-00-00 00:00:00'; $failTimes = $fails; @@ -873,15 +878,15 @@ class userModel extends model } /** - * Check whether the user is locked. - * - * @param int $account + * Check whether the user is locked. + * + * @param int $account * @access public * @return void */ public function checkLocked($account) { - $user = $this->dao->select('locked')->from(TABLE_USER)->where('account')->eq($account)->fetch(); + $user = $this->dao->select('locked')->from(TABLE_USER)->where('account')->eq($account)->fetch(); if(empty($user)) return false; if((strtotime(date('Y-m-d H:i:s')) - strtotime($user->locked)) > $this->config->user->lockMinutes * 60) return false; @@ -889,9 +894,9 @@ class userModel extends model } /** - * Unlock the locked user. - * - * @param int $account + * Unlock the locked user. + * + * @param int $account * @access public * @return void */ @@ -901,9 +906,9 @@ class userModel extends model } /** - * Unbind Ranzhi - * - * @param string $account + * Unbind Ranzhi + * + * @param string $account * @access public * @return void */ @@ -914,7 +919,7 @@ class userModel extends model /** * Get contact list of a user. - * + * * @param string $account * @param string $params withempty|withnote * @@ -960,8 +965,8 @@ class userModel extends model /** * Get a contact list by id. - * - * @param int $listID + * + * @param int $listID * @access public * @return object */ @@ -972,8 +977,8 @@ class userModel extends model /** * Get user account and realname pairs from a contact list. - * - * @param string $accountList + * + * @param string $accountList * @access public * @return array */ @@ -984,9 +989,9 @@ class userModel extends model /** * Create a contact list. - * - * @param string $listName - * @param string $userList + * + * @param string $listName + * @param string $userList * @access public * @return int */ @@ -1013,10 +1018,10 @@ class userModel extends model /** * Update a contact list. - * - * @param int $listID - * @param string $listName - * @param string $userList + * + * @param int $listID + * @param string $listName + * @param string $userList * @access public * @return void */ @@ -1065,8 +1070,8 @@ class userModel extends model /** * Delete a contact list. - * - * @param int $listID + * + * @param int $listID * @access public * @return void */ @@ -1077,8 +1082,8 @@ class userModel extends model /** * Get data in JSON. - * - * @param object $user + * + * @param object $user * @access public * @return array */ @@ -1094,7 +1099,7 @@ class userModel extends model /** * Get weak users. - * + * * @access public * @return array */ @@ -1142,9 +1147,9 @@ class userModel extends model } /** - * Compute password strength. - * - * @param string $password + * Compute password strength. + * + * @param string $password * @access public * @return int */ @@ -1188,4 +1193,30 @@ class userModel extends model return $strength; } + + /** + * Check Tmp dir. + * + * @access public + * @return void + */ + public function checkTmp() + { + if(!is_dir($this->app->tmpRoot)) mkdir($this->app->tmpRoot, 0755, true); + if(!is_dir($this->app->cacheRoot)) mkdir($this->app->cacheRoot, 0755, true); + if(!is_dir($this->app->logRoot)) mkdir($this->app->logRoot, 0755, true); + if(!is_dir($this->app->logRoot)) return false; + + $file = $this->app->logRoot . DS . 'demo.txt'; + if($fp = @fopen($file, 'a+')) + { + @fclose($fp); + @unlink($file); + } + else + { + return false; + } + return true; + } } diff --git a/module/user/view/create.html.php b/module/user/view/create.html.php index 01bae78aa6..d9a0a506ab 100644 --- a/module/user/view/create.html.php +++ b/module/user/view/create.html.php @@ -24,9 +24,9 @@
            - +
            - + @@ -69,12 +69,6 @@ - diff --git a/module/user/view/edit.html.php b/module/user/view/edit.html.php index 5b6a859e33..80a5c33c43 100644 --- a/module/user/view/edit.html.php +++ b/module/user/view/edit.html.php @@ -39,10 +39,6 @@ - @@ -100,7 +96,7 @@ - + @@ -109,7 +105,7 @@
            user->dept;?>user->dept;?>
            user->commiter;?>
            user->gender;?> user->genderList, 'm');?>
            user->gender;?> user->genderList, $user->gender);?>
            phone, "class='form-control' autocomplete='off'");?> user->address;?> address, "class='form-control' autocomplete='off'");?>
            user->zipcode;?> zipcode, "class='form-control' autocomplete='off'");?>
            - + - @@ -95,11 +89,11 @@ - + - + @@ -107,11 +101,11 @@ - + - + @@ -119,11 +113,11 @@ - + - + diff --git a/module/user/view/project.html.php b/module/user/view/project.html.php index d7d3882904..35f86b240c 100644 --- a/module/user/view/project.html.php +++ b/module/user/view/project.html.php @@ -18,7 +18,7 @@ - + @@ -33,7 +33,7 @@ - + delay)):?> @@ -47,5 +47,5 @@ -
            user->verify;?>
            user->verifyPassword;?>user->verifyPassword;?>
            user->placeholder->verify}'");?> diff --git a/module/user/view/login.html.php b/module/user/view/login.html.php index b232c4519b..15592b4b43 100644 --- a/module/user/view/login.html.php +++ b/module/user/view/login.html.php @@ -60,11 +60,13 @@ if(empty($config->notMd5Pwd))js::import($jsRoot . 'md5.js');
            user->loginWithDemoUser; ?> requestType == 'GET' ? '&' : '?'; - foreach($demoUsers as $demoUser => $demoRealname) + $password = md5('123456'); + $link = inlink('login'); + $link .= strpos($link, '?') !== false ? '&' : '?'; + foreach($demoUsers as $demoAccount => $demoUser) { - if(strpos($this->app->company->admins, ",{$demoUser},") !== false) continue; - echo html::a(inlink('login') . $sign . "account={$demoUser}&password=" . md5(md5('123456') + $this->session->rand), $demoRealname, 'hiddenwin'); + if($demoUser->password != $password) continue; + echo html::a($link . "account={$demoAccount}&password=" . md5($password . $this->session->rand), $demoUser->realname, 'hiddenwin'); } ?>
            diff --git a/module/user/view/profile.html.php b/module/user/view/profile.html.php index 64e3f40f07..9d8f5aee0c 100644 --- a/module/user/view/profile.html.php +++ b/module/user/view/profile.html.php @@ -74,12 +74,6 @@
            user->email;?> email;?>
            user->visits;?> visits;?>
            user->skype;?> skype) echo html::a("callto://$user->skype", $user->skype);?>
            user->qq;?> qq) echo html::a("tencent://message/?uin=$user->qq", $user->qq);?>
            user->yahoo;?> yahoo;?>
            user->gtalk;?> gtalk;?>
            user->wangwang;?> wangwang;?>
            user->mobile;?> mobile;?>
            user->phone;?> phone;?>
            user->address;?> address;?>
            user->zipcode;?> zipcode;?>
            idAB;?> project->code;?>project->name;?>project->name;?> project->begin;?> project->end;?> statusAB;?>
            id);?> code;?>name);?>name);?> begin;?> end;?>
            +
            diff --git a/module/webhook/config.php b/module/webhook/config.php index a559e38e6b..df7384e81f 100644 --- a/module/webhook/config.php +++ b/module/webhook/config.php @@ -5,15 +5,6 @@ $config->webhook->create->requiredFields = 'name, url'; $config->webhook->edit = new stdclass(); $config->webhook->edit->requiredFields = 'name, url'; -$config->webhook->objectTypes['release'] = array('opened', 'edited', 'changestatus'); -$config->webhook->objectTypes['build'] = array('opened', 'edited'); -$config->webhook->objectTypes['testsuite'] = array('opened', 'edited'); -$config->webhook->objectTypes['caselib'] = array('opened', 'edited'); -$config->webhook->objectTypes['testreport'] = array('opened', 'edited'); -$config->webhook->objectTypes['doc'] = array('created', 'edited', 'commented'); -$config->webhook->objectTypes['doclib'] = array('created', 'edited'); -$config->webhook->objectTypes['user'] = array('login', 'logout'); - /* Unset entry to hide actions. */ $config->webhook->objectTypes = array(); $config->webhook->objectTypes['product'] = array('opened', 'edited', 'closed', 'undeleted'); diff --git a/module/webhook/control.php b/module/webhook/control.php index 4aecf53d51..86382877bd 100644 --- a/module/webhook/control.php +++ b/module/webhook/control.php @@ -11,6 +11,12 @@ */ class webhook extends control { + public function __construct($moduleName = '', $methodName = '') + { + parent::__construct($moduleName, $methodName); + $this->loadModel('message'); + } + /** * Browse webhooks. * @@ -54,8 +60,6 @@ class webhook extends control $this->view->title = $this->lang->webhook->api . $this->lang->colon . $this->lang->webhook->create; $this->view->products = $this->loadModel('product')->getPairs(); $this->view->projects = $this->loadModel('project')->getPairs(); - $this->view->objectTypes = $this->webhook->getObjectTypes(); - $this->view->objectActions = $this->webhook->getObjectActions(); $this->view->position[] = html::a(inlink('browse'), $this->lang->webhook->api); $this->view->position[] = html::a(inlink('browse'), $this->lang->webhook->common); $this->view->position[] = $this->lang->webhook->create; @@ -83,8 +87,6 @@ class webhook extends control $this->view->title = $this->lang->webhook->edit . $this->lang->colon . $webhook->name; $this->view->products = $this->loadModel('product')->getPairs(); $this->view->projects = $this->loadModel('project')->getPairs(); - $this->view->objectTypes = $this->webhook->getObjectTypes(); - $this->view->objectActions = $this->webhook->getObjectActions(); $this->view->position[] = html::a(inlink('browse'), $this->lang->webhook->api); $this->view->position[] = html::a(inlink('browse'), $this->lang->webhook->common); $this->view->position[] = $this->lang->webhook->edit; @@ -157,19 +159,20 @@ class webhook extends control return true; } + $now = helper::now(); foreach($dataList as $data) { - $webhook = zget($webhooks, $data->webhook, ''); + $webhook = zget($webhooks, $data->objectID, ''); if($webhook) { $result = $this->webhook->fetchHook($webhook, $data->data); $this->webhook->saveLog($webhook, $data->action, $data->data, $result); } - $this->dao->update(TABLE_WEBHOOKDATAS)->set('status')->eq('sended')->where('id')->eq($data->id)->exec(); + $this->dao->update(TABLE_NOTIFY)->set('status')->eq('sended')->set('sendTime')->eq($now)->where('id')->eq($data->id)->exec(); } - $this->dao->delete()->from(TABLE_WEBHOOKDATAS)->where('status')->eq('sended')->exec(); + $this->dao->delete()->from(TABLE_NOTIFY)->where('status')->eq('sended')->exec(); echo "OK\n"; return true; diff --git a/module/webhook/model.php b/module/webhook/model.php index ce466af534..81a5e6a6a2 100644 --- a/module/webhook/model.php +++ b/module/webhook/model.php @@ -21,7 +21,6 @@ class webhookModel extends model public function getByID($id) { $webhook = $this->dao->select('*')->from(TABLE_WEBHOOK)->where('id')->eq($id)->fetch(); - $webhook->actions = json_decode($webhook->actions); return $webhook; } @@ -41,7 +40,6 @@ class webhookModel extends model ->orderBy($orderBy) ->page($pager) ->fetchAll('id'); - if($decode) foreach($webhooks as $webhook) $webhook->actions = json_decode($webhook->actions); return $webhooks; } @@ -96,42 +94,7 @@ class webhookModel extends model */ public function getDataList() { - return $this->dao->select('*')->from(TABLE_WEBHOOKDATAS)->where('status')->eq('wait')->orderBy('id')->fetchAll('id'); - } - - /** - * Get object types. - * - * @access public - * @return array - */ - public function getObjectTypes() - { - $objectTypes = array(); - foreach($this->config->webhook->objectTypes as $objectType => $actions) - { - $objectTypes[$objectType] = $this->lang->action->objectTypes[$objectType]; - } - return $objectTypes; - } - - /** - * Get object actions. - * - * @access public - * @return array - */ - public function getObjectActions() - { - $objectActions = array(); - foreach($this->config->webhook->objectTypes as $objectType => $actions) - { - foreach($actions as $action) - { - $objectActions[$objectType][$action] = str_replace($this->lang->webhook->trimWords, '', $this->lang->action->label->$action); - } - } - return $objectActions; + return $this->dao->select('*')->from(TABLE_NOTIFY)->where('status')->eq('wait')->andWhere('objectType')->eq('webhook')->orderBy('id')->fetchAll('id'); } /** @@ -151,7 +114,6 @@ class webhookModel extends model ->remove('allParams, allActions') ->get(); $webhook->params = $this->post->params ? implode(',', $this->post->params) . ',text' : 'text'; - $webhook->actions = $this->post->actions ? json_encode($this->post->actions) : '[]'; $this->dao->insert(TABLE_WEBHOOK)->data($webhook) ->batchCheck($this->config->webhook->create->requiredFields, 'notempty') @@ -180,7 +142,6 @@ class webhookModel extends model ->remove('allParams, allActions') ->get(); $webhook->params = $this->post->params ? implode(',', $this->post->params) . ',text' : 'text'; - $webhook->actions = $this->post->actions ? json_encode($this->post->actions) : '[]'; $this->dao->update(TABLE_WEBHOOK)->data($webhook) ->batchCheck($this->config->webhook->edit->requiredFields, 'notempty') @@ -208,7 +169,6 @@ class webhookModel extends model foreach($webhooks as $id => $webhook) { - if(!isset($webhook->actions->$objectType) or !in_array($actionType, $webhook->actions->$objectType)) continue; $postData = $this->buildData($objectType, $objectID, $actionType, $actionID, $webhook); if(!$postData) continue; @@ -435,13 +395,14 @@ class webhookModel extends model public function saveData($webhookID, $actionID, $data) { $webhookData = new stdclass(); - $webhookData->webhook = $webhookID; + $webhookData->objectType = 'webhook'; + $webhookData->objectID = $webhookID; $webhookData->action = $actionID; $webhookData->data = $data; $webhookData->createdBy = $this->app->user->account; $webhookData->createdDate = helper::now(); - $this->dao->insert(TABLE_WEBHOOKDATAS)->data($webhookData)->exec(); + $this->dao->insert(TABLE_NOTIFY)->data($webhookData)->exec(); return !dao::isError(); } diff --git a/module/webhook/view/create.html.php b/module/webhook/view/create.html.php index 0ac100cbf2..8e201e6f7d 100644 --- a/module/webhook/view/create.html.php +++ b/module/webhook/view/create.html.php @@ -10,16 +10,10 @@ * @link http://www.zentao.net */ ?> - + webhook->note->typeList);?>
            -
            -
            - webhook->api;?> - webhook->create;?> -
            -
            @@ -60,27 +54,6 @@ - - - - diff --git a/module/webhook/view/edit.html.php b/module/webhook/view/edit.html.php index cb45e9f8ed..4bf7adfdd7 100644 --- a/module/webhook/view/edit.html.php +++ b/module/webhook/view/edit.html.php @@ -10,15 +10,9 @@ * @link http://www.zentao.net */ ?> - +
            -
            -
            - webhook->api;?> - webhook->edit;?> -
            -
            webhook->paramsList, 'text');?>
            - - - - webhook->objectTypes as $objectType => $actions):?> - - - - - -
            - -
            -
            webhook->desc;?>
            @@ -63,28 +57,6 @@ - - - - diff --git a/module/webhook/view/header.html.php b/module/webhook/view/header.html.php index 3458d7405e..6d0254836c 100644 --- a/module/webhook/view/header.html.php +++ b/module/webhook/view/header.html.php @@ -13,8 +13,14 @@
            diff --git a/module/webhook/view/log.html.php b/module/webhook/view/log.html.php index 5ef11c07b1..24498abe57 100644 --- a/module/webhook/view/log.html.php +++ b/module/webhook/view/log.html.php @@ -10,7 +10,7 @@ * @link http://www.zentao.net */ ?> - +
            webhook->common);?> diff --git a/tools/check.php b/tools/check.php index d0b398aba4..843f16fd6b 100755 --- a/tools/check.php +++ b/tools/check.php @@ -193,11 +193,9 @@ foreach(glob($moduleRoot . '*') as $modulePath) $lines = file($langFile); foreach($mainLines as $lineNO => $line) { - if(strpos($line, '$lang') === false) - { - //if($line != $lines[$lineNO]) echo $moduleName . ' ' . $langKey . ' ' . $lineNO . "\n"; - } - else + if(!isset($lines[$lineNO]) OR empty(trim($lines[$lineNO]))) continue; + if(empty(trim($line))) continue; + if(strpos($line, '$lang') === 0) { if(strpos($line, '=') !== false) { diff --git a/www/index.php b/www/index.php index 7fd8a00c87..de622f3c62 100644 --- a/www/index.php +++ b/www/index.php @@ -40,7 +40,7 @@ if(isset($_GET['mode']) and $_GET['mode'] == 'getconfig') die(helper::removeUTF8 /* Check for need upgrade. */ $config->installedVersion = $common->loadModel('setting')->getVersion(); -if(!(!is_numeric($config->version{0}) and $config->version{0} != $config->installedVersion{0}) and version_compare($config->version, $config->installedVersion, '>')) die(header('location: upgrade.php')); +if(((is_numeric($config->version{0}) and is_numeric($config->installedVersion{0})) or $config->version{0} == $config->installedVersion{0}) and version_compare($config->version, $config->installedVersion, '>')) die(header('location: upgrade.php')); /* Remove install.php and upgrade.php. */ if(file_exists('install.php') or file_exists('upgrade.php')) diff --git a/www/js/my.full.js b/www/js/my.full.js index 5ab6d30827..ba37f3ae16 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -15,7 +15,16 @@ function createLink(moduleName, methodName, vars, viewType, isOnlyBody) if(vars) { vars = vars.split('&'); - for(i = 0; i < vars.length; i ++) vars[i] = vars[i].split('='); + for(i = 0; i < vars.length; i ++) + { + splited = vars[i].split('='); + + var newvars = new Array() + newvars[0] = splited.shift(); + newvars[1] = splited.join('='); + + vars[i] = newvars; + } } if(config.requestType != 'GET') { @@ -48,11 +57,11 @@ function createLink(moduleName, methodName, vars, viewType, isOnlyBody) */ function setSearchBox() { - $('#typeSelector a').click(function() + $('#searchTypeMenu a').click(function() { - $('#typeSelector li.active').removeClass('active'); + $('#searchTypeMenu li.selected').removeClass('selected'); var $this = $(this); - $this.closest('li').addClass('active'); + $this.closest('li').addClass('selected'); $("#searchType").val($this.data('value')); $("#searchTypeName").text($this.text()); }); @@ -67,7 +76,7 @@ function setSearchBox() function shortcut() { objectType = $('#searchType').attr('value'); - objectValue = $('#searchQuery').attr('value'); + objectValue = $("input#searchInput").attr('value'); if(objectType && objectValue) { method = objectType == 'testsuite' ? 'library' : 'view'; @@ -1986,6 +1995,34 @@ function selectFocusJump(type) } } +function adjustNoticePosition() +{ + var bottom = 25; + $('#noticeBox').find('.alert').each(function() + { + $(this).css('bottom', bottom + 'px'); + bottom += $(this).outerHeight(true) - 10; + }); +} + +function notifyMessage(data) +{ + if(window.Notification) + { + if(Notification.permission == "granted") + { + new Notification("", {body:data}); + } + else if(Notification.permission != "denied") + { + Notification.requestPermission(function(permission) + { + new Notification("", {body:data}); + }); + } + } +} + /* Ping the server every some minutes to keep the session. */ needPing = true; @@ -2013,7 +2050,7 @@ $(document).ready(function() fixStyle(); // Init tree menu - $('.tree').tree({name: config.currentModule + '-' + config.currentMethod, initialState: 'preserve'}); + $('.tree').tree({initialState: 'preserve'}); $(window).resize(saveWindowSize); // When window resized, call it again. diff --git a/www/js/zui/min.js b/www/js/zui/min.js index 2a4850a429..0abeeb43f1 100644 --- a/www/js/zui/min.js +++ b/www/js/zui/min.js @@ -1,23 +1,59 @@ /*! - * ZUI: zui for zentao - v1.7.0 - 2017-08-22 + * ZUI: Zentao template - v1.8.1 - 2018-03-30 * http://zui.sexy * GitHub: https://github.com/easysoft/zui.git - * Copyright (c) 2017 cnezsoft.com; Licensed MIT + * Copyright (c) 2018 cnezsoft.com; Licensed MIT */ -/*! Some code copy from Bootstrap v3.0.0 by @fat and @mdo. (Copyright 2013 Twitter, Inc. Licensed under http://www.apache.org/licenses/)*/ -!function(t,e,a){"use strict";if("undefined"==typeof t)throw new Error("ZUI requires jQuery");t.zui||(t.zui=function(e){t.isPlainObject(e)&&t.extend(t.zui,e)});var i={all:-1,left:0,middle:1,right:2},o=0;t.zui({uuid:function(){return 1e3*(new Date).getTime()+o++%1e3},callEvent:function(e,i,o){if(t.isFunction(e)){o!==a&&(e=t.proxy(e,o));var n=e(i);return i&&(i.result=n),!(n!==a&&!n)}return 1},clientLang:function(){var a,i=e.config;if("undefined"!=typeof i&&i.clientLang&&(a=i.clientLang),!a){var o=t("html").attr("lang");a=o?o:navigator.userLanguage||navigator.userLanguage||"zh_cn"}return a.replace("-","_").toLowerCase()},strCode:function(t){var e=0;if(t&&t.length)for(var a=0;a0&&(o=n.data(e.substring(s+1))),o&&o.options){var d=o.options[r];t.isFunction(d)&&(l.result=t.zui.callEvent(d,l,o))}return n.trigger(l),l}}(jQuery,window,void 0),function(){"use strict";String.prototype.format||(String.prototype.format=function(t){var e=this;if(arguments.length>0){var a;if(arguments.length<=2&&"object"==typeof t)for(var i in t)void 0!==t[i]&&(a=new RegExp("("+(arguments[1]?arguments[1].replace("0",i):"{"+i+"}")+")","g"),e=e.replace(a,t[i]));else for(var o=0;o0&&(n=a.data(e.substring(o+1))),n&&n.options){var h=n.options[r];t.isFunction(h)&&(l.result=t.zui.callEvent(h,l,n))}return a.trigger(l),l},t.fn.callComEvent=function(e,s,n){n===i||t.isArray(n)||(n=[n]);var a=this,o=a.triggerHandler(s,n),r=e.options[s];return r&&(o=r.apply(e,n)),o}}(jQuery,window,void 0),function(t){"use strict";t.fn.fixOlPd=function(e){return e=e||10,this.each(function(){var i=t(this);i.css("paddingLeft",Math.ceil(Math.log10(i.children().length))*e+10)})},t(function(){t(".ol-pd-fix,.article ol").fixOlPd()})}(jQuery),+function(t){"use strict";var e='[data-dismiss="alert"]',i="zui.alert",s=function(i){t(i).on("click",e,this.close)};s.prototype.close=function(e){function s(){o.trigger("closed."+i).remove()}var n=t(this),a=n.attr("data-target");a||(a=n.attr("href"),a=a&&a.replace(/.*(?=#[^\s]*$)/,""));var o=t(a);e&&e.preventDefault(),o.length||(o=n.hasClass("alert")?n:n.parent()),o.trigger(e=t.Event("close."+i)),e.isDefaultPrevented()||(o.removeClass("in"),t.support.transition&&o.hasClass("fade")?o.one(t.support.transition.end,s).emulateTransitionEnd(150):s())};var n=t.fn.alert;t.fn.alert=function(e){return this.each(function(){var n=t(this),a=n.data(i);a||n.data(i,a=new s(this)),"string"==typeof e&&a[e].call(n)})},t.fn.alert.Constructor=s,t.fn.alert.noConflict=function(){return t.fn.alert=n,this},t(document).on("click."+i+".data-api",e,s.prototype.close)}(window.jQuery),function(t,e){"use strict";var i="zui.pager",s={page:1,recTotal:0,recPerPage:10},n={zh_cn:{prev:"上一页",next:"下一页",first:"第一页",last:"最后一页","goto":"跳转",pageOf:"第 {page} 页",totalPage:"共 {totalPage} 页",totalCount:"共 {recTotal} 项",pageSize:"每页 {recPerPage} 项",itemsRange:"第 {start} ~ {end} 项",pageOfTotal:"第 {page}/{totalPage} 页"},zh_tw:{prev:"上一頁",next:"下一頁",first:"第一頁",last:"最後一頁","goto":"跳轉",pageOf:"第 {page} 頁",totalPage:"共 {totalPage} 頁",totalCount:"共 {recTotal} 項",pageSize:"每頁 {recPerPage} 項",itemsRange:"第 {start} ~ {end} 項",pageOfTotal:"第 {page}/{totalPage} 頁"},en:{prev:"Prev",next:"Next",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"{recTotal} items",pageSize:"{recPerPage} items per page",itemsRange:"From {start} to {end}",pageOfTotal:"Page {page} of {totalPage}"}},a=function(e,s){var o=this;o.name=i,o.$=t(e),s=o.options=t.extend({},a.DEFAULTS,this.$.data(),s);var r=s.lang||"zh_cn";o.lang=t.isPlainObject(r)?t.extend(!0,{},n[r.lang||t.zui.clientLang()],r):n[r],o.state={},o.set(s.page,s.recTotal,s.recPerPage,!0),o.$.on("click",".pager-goto-btn",function(){var e=t(this).closest(".pager-goto"),i=parseInt(e.find(".pager-goto-input").val());NaN!==i&&o.set(i)}).on("click",".pager-item",function(){var e=t(this).data("page");"number"==typeof e&&e>0&&o.set(e)}).on("click",".pager-size-menu [data-size]",function(){var e=t(this).data("size");"number"==typeof e&&e>0&&o.set(-1,-1,e)})};a.prototype.set=function(e,i,n,a){var o=this;"object"==typeof e&&null!==e&&(n=e.recPerPage,i=e.recTotal,e=e.page);var r=o.state;r||(r=t.extend({},s));var l=t.extend({},r);return"number"==typeof n&&n>0&&(r.recPerPage=n),"number"==typeof i&&i>=0&&(r.recTotal=i),"number"==typeof e&&e>=0&&(r.page=e),r.totalPage=r.recTotal&&r.recPerPage?Math.ceil(r.recTotal/r.recPerPage):1,r.page=Math.max(0,Math.min(r.page,r.totalPage)),r.pageRecCount=r.recTotal,r.page&&r.recTotal&&(r.page1&&(r.pageRecCount=r.recTotal-r.recPerPage*(r.page-1))),r.skip=r.page>1?(r.page-1)*r.recPerPage:0,r.start=r.skip+1,r.end=r.skip+r.pageRecCount,r.prev=r.page>1?r.page-1:0,r.next=r.page').attr("href",i?a.createLink(i,a.state):"###").html(s);return n||(o=t("
          • ").append(o).toggleClass("active",i===a.state.page).toggleClass("disabled",!i)),o},a.prototype.createNavItems=function(t){var i=this,s=i.$,n=i.state,a=n.totalPage,o=n.page,r=function(t,n){if(t===!1)return void s.append(i.createLinkItem(0,n||i.options.navEllipsisItem));n===e&&(n=t);for(var a=t;a<=n;++a)s.append(i.createLinkItem(a))};t===e&&(t=i.options.maxNavCount||10),r(1),a>1&&(a<=t?r(2,a):oa-t+2?(r(!1),r(a-t+2,a)):(r(!1),r(o-Math.ceil((t-4)/2),o+Math.floor((t-4)/2)),r(!1),r(a)))},a.prototype.createGoto=function(){var e=this,i=this.state,s=t('
            ");return s},a.prototype.createSizeMenu=function(){var e=this,i=this.state,s=t(''),n=e.options.pageSizeOptions;"string"==typeof n&&(n=n.split(","));for(var a=0;a'+o+"
          • ").toggleClass("active",o===i.recPerPage);s.append(r)}return t('
            ').addClass(e.options.menuDirection).append(s)},a.prototype.createElement=function(e,i,s){var n=this,a=t.proxy(n.createLinkItem,n),o=n.lang;switch(e){case"prev":return a(s.prev,o.prev);case"prev_icon":return a(s.prev,'');case"next":return a(s.next,o.next);case"next_icon":return a(s.next,'');case"first":return a(1,o.first,!0);case"first_icon":return a(1,'',!0);case"last":return a(s.totalPage,o.last,!0);case"last_icon":return a(s.totalPage,'',!0);case"space":case"|":return t('
          • ');case"nav":case"pages":return void n.createNavItems();case"total_text":return t(('
            '+o.totalCount+"
            ").format(s));case"page_text":return t(('
            '+o.pageOf+"
            ").format(s));case"total_page_text":return t(('
            '+o.totalPage+"
            ").format(s));case"page_of_total_text":return t(('
            '+o.pageOfTotal+"
            ").format(s));case"page_size_text":return t(('
            '+o.pageSize+"
            ").format(s));case"items_range_text":return t(('
            '+o.itemsRange+"
            ").format(s));case"goto":return n.createGoto();case"size_menu":return n.createSizeMenu();default:return t("
          • ").html(e)}},a.prototype.createLink=function(i,s){i===e&&(i=this.state.page),s===e&&(s=this.state);var n=this.options.linkCreator;return"string"==typeof n?n.format(t.extend({},s,{page:i})):t.isFunction(n)?n(i,s):"#page="+i},a.prototype.render=function(e){var i=this,s=i.state,n=i.options.elementCreator||i.createElement,a=t.isPlainObject(n);e=e||i.elements||i.options.elements,"string"==typeof e&&(e=e.split(",")),i.elements=e,i.$.empty();for(var o=0;o").append(h)),i.$.append(h))}var c=null;return i.$.children("li").each(function(){var e=t(this),i=!!e.children(".pager-item").length;c?c.toggleClass("pager-item-right",!i):i&&e.addClass("pager-item-left"),c=i?e:null}),c&&c.addClass("pager-item-right"),i.$.callComEvent(i,"onRender",[s]),i},a.DEFAULTS=t.extend({elements:["first_icon","prev_icon","pages","next_icon","last_icon","page_of_total_text","items_range_text","total_text"],prevIcon:"icon-double-angle-left",nextIcon:"icon-double-angle-right",firstIcon:"icon-step-backward",lastIcon:"icon-step-forward",navEllipsisItem:'',maxNavCount:10,menuDirection:"dropdown",pageSizeOptions:[10,20,30,50,100]},s),t.fn.pager=function(e){return this.each(function(){var s=t(this),n=s.data(i),o="object"==typeof e&&e;n||s.data(i,n=new a(this,o)),"string"==typeof e&&n[e]()})},a.NAME=i,t.fn.pager.Constructor=a,t(function(){t('[data-ride="pager"]').pager()})}(jQuery,void 0),+function(t){"use strict";var e="zui.tab",i=function(e){this.element=t(e)};i.prototype.show=function(){var i=this.element,s=i.closest("ul:not(.dropdown-menu)"),n=i.attr("data-target")||i.attr("data-tab");if(n||(n=i.attr("href"),n=n&&n.replace(/.*(?=#[^\s]*$)/,"")),!i.parent("li").hasClass("active")){var a=s.find(".active:last a")[0],o=t.Event("show."+e,{relatedTarget:a});if(i.trigger(o),!o.isDefaultPrevented()){var r=t(n);this.activate(i.parent("li"),s),this.activate(r,r.parent(),function(){i.trigger({type:"shown."+e,relatedTarget:a})})}}},i.prototype.activate=function(e,i,s){function n(){a.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),e.addClass("active"),o?(e[0].offsetWidth,e.addClass("in")):e.removeClass("fade"),e.parent(".dropdown-menu")&&e.closest("li.dropdown").addClass("active"),s&&s()}var a=i.find("> .active"),o=s&&t.support.transition&&a.hasClass("fade");o?a.one(t.support.transition.end,n).emulateTransitionEnd(150):n(),a.removeClass("in")};var s=t.fn.tab;t.fn.tab=function(s){return this.each(function(){var n=t(this),a=n.data(e);a||n.data(e,a=new i(this)),"string"==typeof s&&a[s]()})},t.fn.tab.Constructor=i,t.fn.tab.noConflict=function(){return t.fn.tab=s,this},t(document).on("click.zui.tab.data-api",'[data-toggle="tab"], [data-tab]',function(e){e.preventDefault(),t(this).tab("show")})}(window.jQuery),+function(t){"use strict";function e(){var t=document.createElement("bootstrap"),e={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var i in e)if(void 0!==t.style[i])return{end:e[i]};return!1}t.fn.emulateTransitionEnd=function(e){var i=!1,s=this;t(this).one("bsTransitionEnd",function(){i=!0});var n=function(){i||t(s).trigger(t.support.transition.end)};return setTimeout(n,e),this},t(function(){t.support.transition=e(),t.support.transition&&(t.event.special.bsTransitionEnd={bindType:t.support.transition.end,delegateType:t.support.transition.end,handle:function(e){if(t(e.target).is(this))return e.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(t){"use strict";var e="zui.collapse",i=function(e,s){this.$element=t(e),this.options=t.extend({},i.DEFAULTS,s),this.transitioning=null,this.options.parent&&(this.$parent=t(this.options.parent)),this.options.toggle&&this.toggle()};i.DEFAULTS={toggle:!0},i.prototype.dimension=function(){var t=this.$element.hasClass("width");return t?"width":"height"},i.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var i=t.Event("show."+e);if(this.$element.trigger(i),!i.isDefaultPrevented()){var s=this.$parent&&this.$parent.find(".in");if(s&&s.length){var n=s.data(e);if(n&&n.transitioning)return;s.collapse("hide"),n||s.data(e,null)}var a=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[a](0),this.transitioning=1;var o=function(){this.$element.removeClass("collapsing").addClass("in")[a]("auto"),this.transitioning=0,this.$element.trigger("shown."+e)};if(!t.support.transition)return o.call(this);var r=t.camelCase(["scroll",a].join("-"));this.$element.one(t.support.transition.end,t.proxy(o,this)).emulateTransitionEnd(350)[a](this.$element[0][r])}}},i.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var i=t.Event("hide."+e);if(this.$element.trigger(i),!i.isDefaultPrevented()){var s=this.dimension();this.$element[s](this.$element[s]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var n=function(){this.transitioning=0,this.$element.trigger("hidden."+e).removeClass("collapsing").addClass("collapse")};return t.support.transition?void this.$element[s](0).one(t.support.transition.end,t.proxy(n,this)).emulateTransitionEnd(350):n.call(this)}}},i.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var s=t.fn.collapse;t.fn.collapse=function(s){return this.each(function(){var n=t(this),a=n.data(e),o=t.extend({},i.DEFAULTS,n.data(),"object"==typeof s&&s);a||n.data(e,a=new i(this,o)),"string"==typeof s&&a[s]()})},t.fn.collapse.Constructor=i,t.fn.collapse.noConflict=function(){return t.fn.collapse=s,this},t(document).on("click."+e+".data-api","[data-toggle=collapse]",function(i){var s,n=t(this),a=n.attr("data-target")||i.preventDefault()||(s=n.attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,""),o=t(a),r=o.data(e),l=r?"toggle":n.data(),h=n.attr("data-parent"),c=h&&t(h);r&&r.transitioning||(c&&c.find('[data-toggle=collapse][data-parent="'+h+'"]').not(n).addClass("collapsed"),n[o.hasClass("in")?"addClass":"removeClass"]("collapsed")),o.collapse(l)})}(window.jQuery),function(t,e){"use strict";var i=1200,s=992,n=768,a=e(t),o=function(){var t=a.width();e("html").toggleClass("screen-desktop",t>=s&&t=i).toggleClass("screen-tablet",t>=n&&t=s)},r="",l=navigator.userAgent;l.match(/(iPad|iPhone|iPod)/i)?r+=" os-ios":l.match(/android/i)?r+=" os-android":l.match(/Win/i)?r+=" os-windows":l.match(/Mac/i)?r+=" os-mac":l.match(/Linux/i)?r+=" os-linux":l.match(/X11/i)&&(r+=" os-unix"),"ontouchstart"in document.documentElement&&(r+=" is-touchable"),e("html").addClass(r),a.resize(o),o()}(window,jQuery),function(t){"use strict";var e={zh_cn:'您的浏览器版本过低,无法体验所有功能,建议升级或者更换浏览器。 了解更多...',zh_tw:'您的瀏覽器版本過低,無法體驗所有功能,建議升級或者更换瀏覽器。了解更多...',en:'Your browser is too old, it has been unable to experience the colorful internet. We strongly recommend that you upgrade a better one. Learn more...'},i=function(){var t=this.isIE()||this.isIE10()||!1;if(t)for(var e=10;e>5;e--)if(this.isIE(e)){t=e;break}this.ie=t,this.cssHelper()};i.prototype.cssHelper=function(){var e=this.ie,i=t("html");i.toggleClass("ie",e).removeClass("ie-6 ie-7 ie-8 ie-9 ie-10"),e&&i.addClass("ie-"+e).toggleClass("gt-ie-7 gte-ie-8 support-ie",e>=8).toggleClass("lte-ie-7 lt-ie-8 outdated-ie",e<8).toggleClass("gt-ie-8 gte-ie-9",e>=9).toggleClass("lte-ie-8 lt-ie-9",e<9).toggleClass("gt-ie-9 gte-ie-10",e>=10).toggleClass("lte-ie-9 lt-ie-10",e<10)},i.prototype.tip=function(i){var s=t("#browseHappyTip");s.length||(s=t('
            '),s.prependTo("body")),s.find(".content").html(i||this.browseHappyTip||e[t.zui.clientLang()||"zh_cn"])},i.prototype.isIE=function(t){if(10===t)return this.isIE10();var e=document.createElement("b");return e.innerHTML="",1===e.getElementsByTagName("i").length},i.prototype.isIE10=function(){return!1},t.zui({browser:new i}),t(function(){t("body").hasClass("disabled-browser-tip")||t.zui.browser.ie&&t.zui.browser.ie<8&&t.zui.browser.tip()})}(jQuery),function(){"use strict";Date.ONEDAY_TICKS=864e5,Date.prototype.format||(Date.prototype.format=function(t){var e={"M+":this.getMonth()+1,"d+":this.getDate(),"h+":this.getHours(),"m+":this.getMinutes(),"s+":this.getSeconds(),"q+":Math.floor((this.getMonth()+3)/3),"S+":this.getMilliseconds()};/(y+)/i.test(t)&&(t=t.replace(RegExp.$1,(this.getFullYear()+"").substr(4-RegExp.$1.length)));for(var i in e)new RegExp("("+i+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[i]:("00"+e[i]).substr((""+e[i]).length)));return t}),Date.prototype.addMilliseconds||(Date.prototype.addMilliseconds=function(t){return this.setTime(this.getTime()+t),this}),Date.prototype.addDays||(Date.prototype.addDays=function(t){return this.addMilliseconds(t*Date.ONEDAY_TICKS),this}),Date.prototype.clone||(Date.prototype.clone=function(){var t=new Date;return t.setTime(this.getTime()),t}),Date.isLeapYear||(Date.isLeapYear=function(t){return t%4===0&&t%100!==0||t%400===0}),Date.getDaysInMonth||(Date.getDaysInMonth=function(t,e){return[31,Date.isLeapYear(t)?29:28,31,30,31,30,31,31,30,31,30,31][e]}),Date.prototype.isLeapYear||(Date.prototype.isLeapYear=function(){return Date.isLeapYear(this.getFullYear())}),Date.prototype.clearTime||(Date.prototype.clearTime=function(){return this.setHours(0),this.setMinutes(0),this.setSeconds(0),this.setMilliseconds(0),this}),Date.prototype.getDaysInMonth||(Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth())}),Date.prototype.addMonths||(Date.prototype.addMonths=function(t){var e=this.getDate();return this.setDate(1),this.setMonth(this.getMonth()+t),this.setDate(Math.min(e,this.getDaysInMonth())),this}),Date.prototype.getLastWeekday||(Date.prototype.getLastWeekday=function(t){t=t||1;for(var e=this.clone();e.getDay()!=t;)e.addDays(-1);return e.clearTime(),e}),Date.prototype.isSameDay||(Date.prototype.isSameDay=function(t){return t.toDateString()===this.toDateString()}),Date.prototype.isSameWeek||(Date.prototype.isSameWeek=function(t){var e=this.getLastWeekday(),i=e.clone().addDays(7);return t>=e&&t0){var i;if(arguments.length<=2&&"object"==typeof t)for(var s in t)void 0!==t[s]&&(i=new RegExp("("+(arguments[1]?arguments[1].replace("0",s):"{"+s+"}")+")","g"),e=e.replace(i,t[s]));else for(var n=0;ni.length)&&(e=i.length),e-=t.length;var s=i.indexOf(t,e);return s!==-1&&s===e}),String.prototype.startsWith||(String.prototype.startsWith=function(t,e){return e=e||0,this.lastIndexOf(t,e)===e}),String.prototype.includes||(String.prototype.includes=function(){return String.prototype.indexOf.apply(this,arguments)!==-1})}(),/*! * jQuery resize event - v1.1 * http://benalman.com/projects/jquery-resize-plugin/ * Copyright (c) 2010 "Cowboy" Ben Alman * MIT & GPL http://benalman.com/about/license/ */ -function(t,e,a){"$:nomunge";function i(){o=e[r](function(){n.each(function(){var e=t(this),a=e.width(),i=e.height(),o=t.data(this,d);a===o.w&&i===o.h||e.trigger(l,[o.w=a,o.h=i])}),i()},s[c])}var o,n=t([]),s=t.resize=t.extend(t.resize,{}),r="setTimeout",l="resize",d=l+"-special-event",c="delay",p="throttleWindow";s[c]=250,s[p]=!0,t.event.special[l]={setup:function(){if(!s[p]&&this[r])return!1;var e=t(this);n=n.add(e),t.data(this,d,{w:e.width(),h:e.height()}),1===n.length&&i()},teardown:function(){if(!s[p]&&this[r])return!1;var e=t(this);n=n.not(e),e.removeData(d),n.length||clearTimeout(o)},add:function(e){function i(e,i,n){var s=t(this),r=t.data(this,d)||{};r.w=i!==a?i:s.width(),r.h=n!==a?n:s.height(),o.apply(this,arguments)}if(!s[p]&&this[r])return!1;var o;return t.isFunction(e)?(o=e,i):(o=e.handler,void(e.handler=i))}}}(jQuery,this),function(){"use strict";Date.ONEDAY_TICKS=864e5,Date.prototype.format||(Date.prototype.format=function(t){var e={"M+":this.getMonth()+1,"d+":this.getDate(),"h+":this.getHours(),"m+":this.getMinutes(),"s+":this.getSeconds(),"q+":Math.floor((this.getMonth()+3)/3),"S+":this.getMilliseconds()};/(y+)/i.test(t)&&(t=t.replace(RegExp.$1,(this.getFullYear()+"").substr(4-RegExp.$1.length)));for(var a in e)new RegExp("("+a+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[a]:("00"+e[a]).substr((""+e[a]).length)));return t}),Date.prototype.addMilliseconds||(Date.prototype.addMilliseconds=function(t){return this.setTime(this.getTime()+t),this}),Date.prototype.addDays||(Date.prototype.addDays=function(t){return this.addMilliseconds(t*Date.ONEDAY_TICKS),this}),Date.prototype.clone||(Date.prototype.clone=function(){var t=new Date;return t.setTime(this.getTime()),t}),Date.isLeapYear||(Date.isLeapYear=function(t){return t%4===0&&t%100!==0||t%400===0}),Date.getDaysInMonth||(Date.getDaysInMonth=function(t,e){return[31,Date.isLeapYear(t)?29:28,31,30,31,30,31,31,30,31,30,31][e]}),Date.prototype.isLeapYear||(Date.prototype.isLeapYear=function(){return Date.isLeapYear(this.getFullYear())}),Date.prototype.clearTime||(Date.prototype.clearTime=function(){return this.setHours(0),this.setMinutes(0),this.setSeconds(0),this.setMilliseconds(0),this}),Date.prototype.getDaysInMonth||(Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth())}),Date.prototype.addMonths||(Date.prototype.addMonths=function(t){var e=this.getDate();return this.setDate(1),this.setMonth(this.getMonth()+t),this.setDate(Math.min(e,this.getDaysInMonth())),this}),Date.prototype.getLastWeekday||(Date.prototype.getLastWeekday=function(t){t=t||1;for(var e=this.clone();e.getDay()!=t;)e.addDays(-1);return e.clearTime(),e}),Date.prototype.isSameDay||(Date.prototype.isSameDay=function(t){return t.toDateString()===this.toDateString()}),Date.prototype.isSameWeek||(Date.prototype.isSameWeek=function(t){var e=this.getLastWeekday(),a=e.clone().addDays(7);return t>=e&&t=0;t--)delete this.page[a[t]];this.set(n,this.page)}},s.prototype.pageRemove=function(t){"undefined"!=typeof this.page[t]&&(this.page[t]=null,this.pageSave())},s.prototype.pageClear=function(){this.page={},this.pageSave()},s.prototype.pageGet=function(t,e){var a=this.page[t];return void 0===e||null!==a&&void 0!==a?a:e},s.prototype.pageSet=function(t,a){e.isPlainObject(t)?e.extend(!0,this.page,t):this.page[this.serialize(t)]=a,this.pageSave()},s.prototype.check=function(){if(!this.enable&&!this.slience)throw new Error("Browser not support localStorage or enable status been set true.");return this.enable},s.prototype.length=function(){return this.check()?a.getLength?a.getLength():a.length:0},s.prototype.removeItem=function(t){return a.removeItem(t),this},s.prototype.remove=function(t){return this.removeItem(t)},s.prototype.getItem=function(t){return a.getItem(t)},s.prototype.get=function(t,e){var a=this.deserialize(this.getItem(t));return"undefined"!=typeof a&&null!==a||"undefined"==typeof e?a:e},s.prototype.key=function(t){return a.key(t)},s.prototype.setItem=function(t,e){return a.setItem(t,e),this},s.prototype.set=function(t,e){return void 0===e?this.remove(t):(this.setItem(t,this.serialize(e)),this)},s.prototype.clear=function(){return a.clear(),this},s.prototype.forEach=function(t){for(var e=this.length(),i=e-1;i>=0;i--){var o=a.key(i);t(o,this.get(o))}return this},s.prototype.getAll=function(){var t={};return this.forEach(function(e,a){t[e]=a}),t},s.prototype.serialize=function(t){return"string"==typeof t?t:JSON.stringify(t)},s.prototype.deserialize=function(t){if("string"==typeof t)try{return JSON.parse(t)}catch(e){return t||void 0}},e.zui({store:new s})}(window,jQuery),function(t,e,a,i){"use strict";function o(t){if(t=t.toLowerCase(),t&&c.test(t)){var e;if(4===t.length){var a="#";for(e=1;e<4;e+=1)a+=t.slice(e,e+1).concat(t.slice(e,e+1));t=a}var i=[];for(e=1;e<7;e+=2)i.push(y("0x"+t.slice(e,e+2)));return{r:i[0],g:i[1],b:i[2],a:1}}throw new Error("Wrong hex string! (hex: "+t+")")}function n(e){return typeof e===u&&("transparent"===e.toLowerCase()||v[e.toLowerCase()]||c.test(t.trim(e.toLowerCase())))}function s(t){function e(t){return t=t<0?t+1:t>1?t-1:t,6*t<1?r+(s-r)*t*6:2*t<1?s:3*t<2?r+(s-r)*(2/3-t)*6:r}var a=t.h,i=t.s,o=t.l,n=t.a;a=d(a)%h/h,i=l(d(i)),o=l(d(o)),n=l(d(n));var s=o<=.5?o*(i+1):o+i-o*i,r=2*o-s,c={r:e(a+1/3)*p,g:e(a)*p,b:e(a-1/3)*p,a:n};return c}function r(t,a,i){return m(i)&&(i=0),m(a)&&(a=p),e.min(e.max(t,i),a)}function l(t,e){return r(t,e)}function d(t){return"number"==typeof t?t:parseFloat(t)}var c=/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/,p=255,h=360,f=100,u="string",g="object",v={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"},m=function(t){return t===i},b=function(t){return!m(t)},y=function(t){return parseInt(t)},w=function(t){return y(l(d(t),p))},C=function(t,e,a,i){var n=this;if(n.r=n.g=n.b=0,n.a=1,b(i)&&(n.a=l(d(i),1)),b(t)&&b(e)&&b(a))n.r=w(t),n.g=w(e),n.b=w(a);else if(b(t)){var r=typeof t;if(r==u)t=t.toLowerCase(),"transparent"===t?n.a=0:v[t]?this.rgb(o(v[t])):n.rgb(o(t));else if("number"==r&&m(e))n.r=n.g=n.b=w(t);else if(r==g&&b(t.r))n.r=w(t.r),b(t.g)&&(n.g=w(t.g)),b(t.b)&&(n.b=w(t.b)),b(t.a)&&(n.a=l(d(t.a),1));else if(r==g&&b(t.h)){var c={h:l(d(t.h),h),s:1,l:1,a:1};b(t.s)&&(c.s=l(d(t.s),1)),b(t.l)&&(c.l=l(d(t.l),1)),b(t.a)&&(c.a=l(d(t.a),1)),n.rgb(s(c))}}};C.prototype.rgb=function(t){var e=this;if(b(t)){if(typeof t==g)b(t.r)&&(e.r=w(t.r)),b(t.g)&&(e.g=w(t.g)),b(t.b)&&(e.b=w(t.b)),b(t.a)&&(e.a=l(d(t.a),1));else{var a=y(d(t));e.r=a,e.g=a,e.b=a}return e}return{r:e.r,g:e.g,b:e.b,a:e.a}},C.prototype.hue=function(t){var e=this,a=e.toHsl();return m(t)?a.h:(a.h=l(d(t),h),e.rgb(s(a)),e)},C.prototype.darken=function(t){var e=this,a=e.toHsl();return a.l-=t/f,a.l=l(a.l,1),e.rgb(s(a)),e},C.prototype.clone=function(){var t=this;return new C(t.r,t.g,t.b,t.a)},C.prototype.lighten=function(t){return this.darken(-t)},C.prototype.fade=function(t){return this.a=l(t/f,1),this},C.prototype.spin=function(t){var e=this.toHsl(),a=(e.h+t)%h;return e.h=a<0?h+a:a,this.rgb(s(e))},C.prototype.toHsl=function(){var t,a,i=this,o=i.r/p,n=i.g/p,s=i.b/p,r=i.a,l=e.max(o,n,s),d=e.min(o,n,s),c=(l+d)/2,f=l-d;if(l===d)t=a=0;else{switch(a=c>.5?f/(2-l-d):f/(l+d),l){case o:t=(n-s)/f+(ne.luma()){var i=e;e=t,t=i}return this.a<.5?t:(a=m(a)?.43:d(a),this.luma()0?t.a<1?"rgba("+t.r+","+t.g+","+t.b+","+t.a+")":t.hexStr():"transparent"},C.isColor=n,C.names=v,C.get=function(t){return new C(t)},t.zui({Color:C})}(jQuery,Math,window,void 0),/*! - * ZUI: Generated from less code - v1.7.0 - 2017-08-22 - * http://zui.sexy - * GitHub: https://github.com/easysoft/zui.git - * Copyright (c) 2017 cnezsoft.com; Licensed MIT +function(t,e,i){"$:nomunge";function s(){n=e[r](function(){a.each(function(){var e=t(this),i=e.width(),s=e.height(),n=t.data(this,h);i===n.w&&s===n.h||e.trigger(l,[n.w=i,n.h=s])}),s()},o[c])}var n,a=t([]),o=t.resize=t.extend(t.resize,{}),r="setTimeout",l="resize",h=l+"-special-event",c="delay",d="throttleWindow";o[c]=250,o[d]=!0,t.event.special[l]={setup:function(){if(!o[d]&&this[r])return!1;var e=t(this);a=a.add(e),t.data(this,h,{w:e.width(),h:e.height()}),1===a.length&&s()},teardown:function(){if(!o[d]&&this[r])return!1;var e=t(this);a=a.not(e),e.removeData(h),a.length||clearTimeout(n)},add:function(e){function s(e,s,a){var o=t(this),r=t.data(this,h)||{};r.w=s!==i?s:o.width(),r.h=a!==i?a:o.height(),n.apply(this,arguments)}if(!o[d]&&this[r])return!1;var n;return t.isFunction(e)?(n=e,s):(n=e.handler,void(e.handler=s))}}}(jQuery,this),function(t,e){"use strict";var i,s,n="localStorage",a="page_"+t.location.pathname+t.location.search,o=function(){this.slience=!0;try{n in t&&t[n]&&t[n].setItem&&(this.enable=!0,i=t[n])}catch(o){}this.enable||(s={},i={getLength:function(){var t=0;return e.each(s,function(){t++}),t},key:function(t){var i,n=0;return e.each(s,function(e){return n===t?(i=e,!1):void n++}),i},removeItem:function(t){delete s[t]},getItem:function(t){return s[t]},setItem:function(t,e){s[t]=e},clear:function(){s={}}}),this.storage=i,this.page=this.get(a,{})};o.prototype.pageSave=function(){if(e.isEmptyObject(this.page))this.remove(a);else{var t,i=[];for(t in this.page){var s=this.page[t];null===s&&i.push(t)}for(t=i.length-1;t>=0;t--)delete this.page[i[t]];this.set(a,this.page)}},o.prototype.pageRemove=function(t){"undefined"!=typeof this.page[t]&&(this.page[t]=null,this.pageSave())},o.prototype.pageClear=function(){this.page={},this.pageSave()},o.prototype.pageGet=function(t,e){var i=this.page[t];return void 0===e||null!==i&&void 0!==i?i:e},o.prototype.pageSet=function(t,i){e.isPlainObject(t)?e.extend(!0,this.page,t):this.page[this.serialize(t)]=i,this.pageSave()},o.prototype.check=function(){if(!this.enable&&!this.slience)throw new Error("Browser not support localStorage or enable status been set true.");return this.enable},o.prototype.length=function(){return this.check()?i.getLength?i.getLength():i.length:0},o.prototype.removeItem=function(t){return i.removeItem(t),this},o.prototype.remove=function(t){return this.removeItem(t)},o.prototype.getItem=function(t){return i.getItem(t)},o.prototype.get=function(t,e){var i=this.deserialize(this.getItem(t));return"undefined"!=typeof i&&null!==i||"undefined"==typeof e?i:e},o.prototype.key=function(t){return i.key(t)},o.prototype.setItem=function(t,e){return i.setItem(t,e),this},o.prototype.set=function(t,e){return void 0===e?this.remove(t):(this.setItem(t,this.serialize(e)),this)},o.prototype.clear=function(){return i.clear(),this},o.prototype.forEach=function(t){for(var e=this.length(),s=e-1;s>=0;s--){var n=i.key(s);t(n,this.get(n))}return this},o.prototype.getAll=function(){var t={};return this.forEach(function(e,i){t[e]=i}),t},o.prototype.serialize=function(t){return"string"==typeof t?t:JSON.stringify(t)},o.prototype.deserialize=function(t){if("string"==typeof t)try{return JSON.parse(t)}catch(e){return t||void 0}},e.zui({store:new o})}(window,jQuery),function(t){"use strict";var e="zui.searchBox",i=function(e,s){var n=this;n.name=name,n.$=t(e),n.options=s=t.extend({},i.DEFAULTS,n.$.data(),s);var a=n.$.is(s.inputSelector)?n.$:n.$.find(s.inputSelector);if(a.length){var o=function(){n.changeTimer&&(clearTimeout(n.changeTimer),n.changeTimer=null)},r=function(){o();var t=n.getSearch();if(t!==n.lastValue){var e=""===t;a.toggleClass("empty",e),n.$.callComEvent(n,"onSearchChange",[t,e]),n.lastValue=t}};n.$input=a=a.first(),n.lastValue=n.getSearch(),a.on(s.listenEvent,function(t){n.changeTimer=setTimeout(function(){r()},s.changeDelay)}).on("focus",function(t){a.addClass("focus"),n.$.callComEvent(n,"onFocus",[t])}).on("blur",function(t){a.removeClass("focus"),n.$.callComEvent(n,"onBlur",[t])}).on("keydown",function(t){var e=0,i=t.which;27===i&&s.escToClear?(this.setSearch("",!0),r(),e=1):13===i&&s.onPressEnter&&(r(),n.$.callComEvent(n,"onPressEnter",[t]));var a=n.$.callComEvent(n,"onKeyDown",[t]);a===!1&&(e=1),e&&t.preventDefault()}),n.$.on("click",".search-clear-btn",function(t){n.setSearch("",!0),r(),t.preventDefault()}),r()}else console.error("ZUI: search box init error, cannot find search box input element.")};i.DEFAULTS={inputSelector:'input[type="search"],input[type="text"]',listenEvent:"change input paste",changeDelay:500},i.prototype.getSearch=function(){return this.$input&&t.trim(this.$input.val())},i.prototype.setSearch=function(t,e){var i=this.$input;i&&(i.val(t),e||i.trigger("change"))},i.prototype.focus=function(){this.$input&&this.$input.focus()},t.fn.searchBox=function(s){return this.each(function(){var n=t(this),a=n.data(e),o="object"==typeof s&&s;a||n.data(e,a=new i(this,o)),"string"==typeof s&&a[s]()})},i.NAME=e,t.fn.searchBox.Constructor=i}(jQuery),function(t,e){"use strict";var i="zui.draggable",s={container:"body",move:!0},n=0,a=function(e,i){var a=this;a.$=t(e),a.id=n++,a.options=t.extend({},s,a.$.data(),i),a.init()};a.DEFAULTS=s,a.NAME=i,a.prototype.init=function(){var s,n,a,o,r,l=this,h=l.$,c="before",d="drag",u="finish",p="."+i+"."+l.id,f="mousedown"+p,g="mouseup"+p,m="mousemove"+p,v=l.options,y=v.selector,w=v.handle,b=h,_=t.isFunction(v.move),x=function(t){var e=t.pageX,i=t.pageY;r=!0;var n={left:e-a.x,top:i-a.y};b.removeClass("drag-ready").addClass("dragging"),v.move&&(_?v.move(n,b):b.css(n)),v[d]&&v[d]({event:t,element:b,startOffset:a,pos:n,offset:{x:e-s.x,y:i-s.y},smallOffset:{x:e-o.x,y:i-o.y}}),o.x=e,o.y=i,v.stopPropagation&&t.stopPropagation()},C=function(i){if(t(e).off(p),!r)return void b.removeClass("drag-ready");var n={left:i.pageX-a.x,top:i.pageY-a.y};b.removeClass("drag-ready dragging"),v.move&&(_?v.move(n,b):b.css(n)),v[u]&&v[u]({event:i,element:b,startOffset:a,pos:n,offset:{x:i.pageX-s.x,y:i.pageY-s.y},smallOffset:{x:i.pageX-o.x,y:i.pageY-o.y}}),i.preventDefault(),v.stopPropagation&&i.stopPropagation()},k=function(i){var l=t.zui.getMouseButtonCode(v.mouseButton);if(!(l>-1&&i.button!==l)){var h=t(this);if(y&&(b=w?h.closest(y):h),v[c]){var d=v[c]({event:i,element:b});if(d===!1)return}var u=t(v.container),p=b.offset();n=u.offset(),s={x:i.pageX,y:i.pageY},a={x:i.pageX-p.left+n.left,y:i.pageY-p.top+n.top},o=t.extend({},s),r=!1,b.addClass("drag-ready"),i.preventDefault(),v.stopPropagation&&i.stopPropagation(),t(e).on(m,x).on(g,C)}};w?h.on(f,w,k):y?h.on(f,y,k):h.on(f,k)},a.prototype.destroy=function(){var s="."+i+"."+this.id;this.$.off(s),t(e).off(s),this.$.data(i,null)},t.fn.draggable=function(e){return this.each(function(){var s=t(this),n=s.data(i),o="object"==typeof e&&e;n||s.data(i,n=new a(this,o)),"string"==typeof e&&n[e]()})},t.fn.draggable.Constructor=a}(jQuery,document),function(t,e,i){"use strict";var s="zui.droppable",n={target:".droppable-target",deviation:5,sensorOffsetX:0,sensorOffsetY:0},a=0,o=function(e,i){var s=this;s.id=a++,s.$=t(e),s.options=t.extend({},n,s.$.data(),i),s.init()};o.DEFAULTS=n,o.NAME=s,o.prototype.trigger=function(e,i){return t.zui.callEvent(this.options[e],i,this)},o.prototype.init=function(){var n,a,o,r,l,h,c,d,u,p,f,g,m,v=this,y=v.$,w=v.options,b=w.deviation,_="."+s+"."+v.id,x="mousedown"+_,C="mouseup"+_,k="mousemove"+_,T=w.selector,S=w.handle,D=w.flex,M=w.container,P=w.canMoveHere,F=y,L=!1,z=M?t(w.container).first():T?y:t("body"),I=function(e){if(L&&(f={left:e.pageX,top:e.pageY},!(i.abs(f.left-d.left)a&&f.top>o&&f.left-1&&i.button!==s)){var f=t(this);T&&(F=S?f.closest(T):f),F.hasClass("drag-shadow")||w.before&&w.before({event:i,element:F})===!1||(L=!0,n=t.isFunction(w.target)?w.target(y):z.find(w.target),a=null,o=null,r=!1,l=!0,h=null,c=F.offset(),u=z.offset(),d={left:i.pageX,top:i.pageY},g=t.extend({},d),p={left:d.left-c.left,top:d.top-c.top},F.addClass("drag-from"),t(e).on(k,I).on(C,A),m=setTimeout(function(){t(e).on(x,A)},10),i.preventDefault())}};S?y.on(x,S,E):T?y.on(x,T,E):y.on(x,E)},o.prototype.destroy=function(){var i="."+s+"."+this.id;this.$.off(i),t(e).off(i),this.$.data(s,null)},o.prototype.reset=function(){this.destroy(),this.init()},t.fn.droppable=function(e){return this.each(function(){var i=t(this),n=i.data(s),a="object"==typeof e&&e;n||i.data(s,n=new o(this,a)),"string"==typeof e&&n[e]()})},t.fn.droppable.Constructor=o}(jQuery,document,Math),+function(t,e){"use strict";function i(e,i,a){return this.each(function(){var o=t(this),r=o.data(s),l=t.extend({},n.DEFAULTS,o.data(),"object"==typeof e&&e);r||o.data(s,r=new n(this,l)),"string"==typeof e?r[e](i,a):l.show&&r.show(i,a)})}var s="zui.modal",n=function(i,n){var a=this;a.options=n,a.$body=t(document.body),a.$element=t(i),a.$backdrop=a.isShown=null,a.scrollbarWidth=0,n.moveable===e&&(a.options.moveable=a.$element.hasClass("modal-moveable")),n.remote&&a.$element.find(".modal-content").load(n.remote,function(){a.$element.trigger("loaded."+s)})};n.VERSION="3.2.0",n.TRANSITION_DURATION=300,n.BACKDROP_TRANSITION_DURATION=150,n.DEFAULTS={backdrop:!0,keyboard:!0,show:!0,position:"fit"};var a=function(e,i){var s=t(window);i.left=Math.max(0,Math.min(i.left,s.width()-e.outerWidth())),i.top=Math.max(0,Math.min(i.top,s.height()-e.outerHeight())),e.css(i)};n.prototype.toggle=function(t,e){return this.isShown?this.hide():this.show(t,e)},n.prototype.ajustPosition=function(i){var n=this,o=n.options;if(i===e&&(i=o.position),i!==e){t.isFunction(i)&&(i=i(n));var r=n.$element.find(".modal-dialog"),l=Math.max(0,(t(window).height()-r.outerHeight())/2);if("fit"===i?i={marginTop:2*l/3}:"center"===i?i={marginTop:l}:t.isPlainObject(i)||(i={marginTop:i}),r.hasClass("modal-moveable")){var h=null,c=o.rememberPos;c&&(c===!0?h=n.$element.data("modal-pos"):t.zui.store&&(h=t.zui.store.pageGet(s+".rememberPos."+c))),i=t.extend(i,{left:Math.max(0,(t(window).width()-r.outerWidth())/2)},h),"inside"===o.moveable?a(r,i):r.css(i)}else r.css(i)}},n.prototype.setMoveale=function(){t.fn.draggable||console.error("Moveable modal requires draggable.js.");var e=this,i=e.options,n=e.$element.find(".modal-dialog").removeClass("modal-dragged");n.toggleClass("modal-moveable",!!i.moveable),e.$element.data("modal-moveable-setup")||n.draggable({container:e.$element,handle:".modal-header",before:function(){n.css("margin-top","").addClass("modal-dragged")},finish:function(n){var a=i.rememberPos;a&&(e.$element.data("modal-pos",n.pos),t.zui.store&&a!==!0&&t.zui.store.pageSet(s+".rememberPos."+a,n.pos))},move:"inside"!==i.moveable||function(t){a(n,t)}})},n.prototype.show=function(e,i){var a=this,o=t.Event("show."+s,{relatedTarget:e});a.$element.trigger(o),a.isShown||o.isDefaultPrevented()||(a.isShown=!0,a.options.moveable&&a.setMoveale(),a.checkScrollbar(),a.options.backdrop!==!1&&(a.$body.addClass("modal-open"),a.setScrollbar()),a.escape(),a.$element.on("click.dismiss."+s,'[data-dismiss="modal"]',t.proxy(a.hide,a)),a.backdrop(function(){var o=t.support.transition&&a.$element.hasClass("fade");a.$element.parent().length||a.$element.appendTo(a.$body),a.$element.show().scrollTop(0),o&&a.$element[0].offsetWidth,a.$element.addClass("in").attr("aria-hidden",!1),a.ajustPosition(i),a.enforceFocus();var r=t.Event("shown."+s,{relatedTarget:e});o?a.$element.find(".modal-dialog").one("bsTransitionEnd",function(){a.$element.trigger("focus").trigger(r)}).emulateTransitionEnd(n.TRANSITION_DURATION):a.$element.trigger("focus").trigger(r)}))},n.prototype.hide=function(e){e&&e.preventDefault();var i=this;e=t.Event("hide."+s),i.$element.trigger(e),i.isShown&&!e.isDefaultPrevented()&&(i.isShown=!1,i.options.backdrop!==!1&&(i.$body.removeClass("modal-open"),i.resetScrollbar()),i.escape(),t(document).off("focusin."+s),i.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss."+s),t.support.transition&&i.$element.hasClass("fade")?i.$element.one("bsTransitionEnd",t.proxy(i.hideModal,i)).emulateTransitionEnd(n.TRANSITION_DURATION):i.hideModal())},n.prototype.enforceFocus=function(){t(document).off("focusin."+s).on("focusin."+s,t.proxy(function(t){this.$element[0]===t.target||this.$element.has(t.target).length||this.$element.trigger("focus")},this))},n.prototype.escape=function(){this.isShown&&this.options.keyboard?t(document).on("keydown.dismiss."+s,t.proxy(function(i){if(27==i.which){var n=t.Event("escaping."+s),a=this.$element.triggerHandler(n,"esc");if(a!=e&&!a)return;this.hide()}},this)):this.isShown||t(document).off("keydown.dismiss."+s)},n.prototype.hideModal=function(){var t=this;this.$element.hide(),this.backdrop(function(){t.$element.trigger("hidden."+s)})},n.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},n.prototype.backdrop=function(e){var i=this,a=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var o=t.support.transition&&a;if(this.$backdrop=t(''),i.prependTo("body")),i.find(".content").html(a||this.browseHappyTip||e[t.zui.clientLang()||"zh_cn"])},a.prototype.isIE=function(t){if(10===t)return this.isIE10();var e=document.createElement("b");return e.innerHTML="",1===e.getElementsByTagName("i").length},a.prototype.isIE10=function(){return!1},t.zui({browser:new a}),t(function(){t("body").hasClass("disabled-browser-tip")||t.zui.browser.ie&&t.zui.browser.ie<8&&t.zui.browser.tip()})}(jQuery),+function(t){"use strict";var e="zui.collapse",a=function(e,i){this.$element=t(e),this.options=t.extend({},a.DEFAULTS,i),this.transitioning=null,this.options.parent&&(this.$parent=t(this.options.parent)),this.options.toggle&&this.toggle()};a.DEFAULTS={toggle:!0},a.prototype.dimension=function(){var t=this.$element.hasClass("width");return t?"width":"height"},a.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var a=t.Event("show."+e);if(this.$element.trigger(a),!a.isDefaultPrevented()){var i=this.$parent&&this.$parent.find(".in");if(i&&i.length){var o=i.data(e);if(o&&o.transitioning)return;i.collapse("hide"),o||i.data(e,null)}var n=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[n](0),this.transitioning=1;var s=function(){this.$element.removeClass("collapsing").addClass("in")[n]("auto"),this.transitioning=0,this.$element.trigger("shown."+e)};if(!t.support.transition)return s.call(this);var r=t.camelCase(["scroll",n].join("-"));this.$element.one(t.support.transition.end,t.proxy(s,this)).emulateTransitionEnd(350)[n](this.$element[0][r])}}},a.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var a=t.Event("hide."+e);if(this.$element.trigger(a),!a.isDefaultPrevented()){var i=this.dimension();this.$element[i](this.$element[i]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var o=function(){this.transitioning=0,this.$element.trigger("hidden."+e).removeClass("collapsing").addClass("collapse")};return t.support.transition?void this.$element[i](0).one(t.support.transition.end,t.proxy(o,this)).emulateTransitionEnd(350):o.call(this)}}},a.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var i=t.fn.collapse;t.fn.collapse=function(i){return this.each(function(){var o=t(this),n=o.data(e),s=t.extend({},a.DEFAULTS,o.data(),"object"==typeof i&&i);n||o.data(e,n=new a(this,s)),"string"==typeof i&&n[i]()})},t.fn.collapse.Constructor=a,t.fn.collapse.noConflict=function(){return t.fn.collapse=i,this},t(document).on("click."+e+".data-api","[data-toggle=collapse]",function(a){var i,o=t(this),n=o.attr("data-target")||a.preventDefault()||(i=o.attr("href"))&&i.replace(/.*(?=#[^\s]+$)/,""),s=t(n),r=s.data(e),l=r?"toggle":o.data(),d=o.attr("data-parent"),c=d&&t(d);r&&r.transitioning||(c&&c.find('[data-toggle=collapse][data-parent="'+d+'"]').not(o).addClass("collapsed"),o[s.hasClass("in")?"addClass":"removeClass"]("collapsed")),s.collapse(l)})}(window.jQuery),+function(t){"use strict";function e(){t(o).remove(),t(n).each(function(e){var o=a(t(this));o.hasClass("open")&&(o.trigger(e=t.Event("hide."+i)),e.isDefaultPrevented()||o.removeClass("open").trigger("hidden."+i))})}function a(e){var a=e.attr("data-target");a||(a=e.attr("href"),a=a&&/#/.test(a)&&a.replace(/.*(?=#[^\s]*$)/,""));var i;try{i=a&&t(a)}catch(o){}return i&&i.length?i:e.parent()}var i="zui.dropdown",o=".dropdown-backdrop",n="[data-toggle=dropdown]",s=function(e){t(e).on("click."+i,this.toggle)};s.prototype.toggle=function(o){var n=t(this);if(!n.is(".disabled, :disabled")){var s=a(n),r=s.hasClass("open");if(e(),!r){if("ontouchstart"in document.documentElement&&!s.closest(".navbar-nav").length&&t('",header:"",footer:"",closeButton:"",form:"",inputs:{text:"",textarea:"",email:"",select:"",checkbox:"
            ",date:"",time:"",number:"",password:""}},u={locale:e.zui&&e.zui.clientLang?e.zui.clientLang():"zh_cn",backdrop:"static",animate:!0,className:null,closeButton:!0,show:!0,container:"body"},g={};g.alert=function(){var t;if(t=c("alert",["ok"],["message","callback"],arguments),t.callback&&!e.isFunction(t.callback))throw new Error("alert requires callback property to be a function when provided");return t.buttons.ok.callback=t.onEscape=function(){return!e.isFunction(t.callback)||t.callback.call(this)},g.dialog(t)},g.confirm=function(){var t;if(t=c("confirm",["confirm","cancel"],["message","callback"],arguments),t.buttons.cancel.callback=t.onEscape=function(){return t.callback.call(this,!1)},t.buttons.confirm.callback=function(){return t.callback.call(this,!0)},!e.isFunction(t.callback))throw new Error("confirm requires a callback");return g.dialog(t)},g.prompt=function(){var t,i,o,n,r,l,c;if(n=e(f.form),i={className:"bootbox-prompt",buttons:p("cancel","confirm"),value:"",inputType:"text"},t=h(d(i,arguments,["title","callback"]),["confirm","cancel"]),l=t.show===a||t.show,t.message=n,t.buttons.cancel.callback=t.onEscape=function(){return t.callback.call(this,null)},t.buttons.confirm.callback=function(){var a;switch(t.inputType){case"text":case"textarea":case"email":case"select":case"date":case"time":case"number":case"password":a=r.val();break;case"checkbox":var i=r.find("input:checked");a=[],s(i,function(t,i){a.push(e(i).val())})}return t.callback.call(this,a)},t.show=!1,!t.title)throw new Error("prompt requires a title");if(!e.isFunction(t.callback))throw new Error("prompt requires a callback");if(!f.inputs[t.inputType])throw new Error("invalid prompt type");switch(r=e(f.inputs[t.inputType]),t.inputType){case"text":case"textarea":case"email":case"date":case"time":case"number":case"password":r.val(t.value);break;case"select":var u={};if(c=t.inputOptions||[],!e.isArray(c))throw new Error("Please pass an array of input options");if(!c.length)throw new Error("prompt with select requires options");s(c,function(t,i){var o=r;if(i.value===a||i.text===a)throw new Error("given options in wrong format");i.group&&(u[i.group]||(u[i.group]=e("").attr("label",i.group)),o=u[i.group]),o.append("")}),s(u,function(t,e){r.append(e)}),r.val(t.value);break;case"checkbox":var v=e.isArray(t.value)?t.value:[t.value];if(c=t.inputOptions||[],!c.length)throw new Error("prompt with checkbox requires options");if(!c[0].value||!c[0].text)throw new Error("given options in wrong format");r=e("
            "),s(c,function(a,i){var o=e(f.inputs[t.inputType]);o.find("input").attr("value",i.value),o.find("label").append(i.text),s(v,function(t,e){e===i.value&&o.find("input").prop("checked",!0)}),r.append(o)})}return t.placeholder&&r.attr("placeholder",t.placeholder),t.pattern&&r.attr("pattern",t.pattern),t.maxlength&&r.attr("maxlength",t.maxlength),n.append(r),n.on("submit",function(t){t.preventDefault(),t.stopPropagation(),o.find(".btn-primary").click()}),o=g.dialog(t),o.off("shown.zui.modal"),o.on("shown.zui.modal",function(){r.focus()}),l===!0&&o.modal("show"),o},g.dialog=function(t){t=r(t);var i=e(f.dialog),n=i.find(".modal-dialog"),l=i.find(".modal-body"),d=t.buttons,c="",p={onEscape:t.onEscape};if(e.fn.modal===a)throw new Error("$.fn.modal is not defined; please double check you have included the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ for more details.");if(s(d,function(t,e){c+="",p[t]=e.callback}),l.find(".bootbox-body").html(t.message),t.animate===!0&&i.addClass("fade"),t.className&&i.addClass(t.className),"large"===t.size?n.addClass("modal-lg"):"small"===t.size&&n.addClass("modal-sm"),t.title&&l.before(f.header),t.closeButton){var h=e(f.closeButton);t.title?i.find(".modal-header").prepend(h):h.css("margin-top","-10px").prependTo(l)}return t.title&&i.find(".modal-title").html(t.title),c.length&&(l.after(f.footer),i.find(".modal-footer").html(c)),i.on("hidden.zui.modal",function(t){t.target===this&&i.remove()}),i.on("shown.zui.modal",function(){i.find(".btn-primary:first").focus()}),"static"!==t.backdrop&&i.on("click.dismiss.zui.modal",function(t){i.children(".modal-backdrop").length&&(t.currentTarget=i.children(".modal-backdrop").get(0)),t.target===t.currentTarget&&i.trigger("escape.close.bb")}),i.on("escape.close.bb",function(t){p.onEscape&&o(t,i,p.onEscape)}),i.on("click",".modal-footer button",function(t){var a=e(this).data("bb-handler");o(t,i,p[a])}),i.on("click",".bootbox-close-button",function(t){o(t,i,p.onEscape)}),i.on("keyup",function(t){27===t.which&&i.trigger("escape.close.bb")}),e(t.container).append(i),i.modal({backdrop:!!t.backdrop&&"static",keyboard:!1,show:!1}),t.show&&i.modal("show"),i},g.setDefaults=function(){var t={};2===arguments.length?t[arguments[0]]=arguments[1]:t=arguments[0],e.extend(u,t)},g.hideAll=function(){return e(".bootbox").modal("hide"),g};var v={en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},zh_cn:{OK:"确认",CANCEL:"取消",CONFIRM:"确认"},zh_tw:{OK:"確認",CANCEL:"取消",CONFIRM:"確認"}};return g.addLocale=function(t,a){return e.each(["OK","CANCEL","CONFIRM"],function(t,e){if(!a[e])throw new Error("Please supply a translation for '"+e+"'")}),v[t]={OK:a.OK,CANCEL:a.CANCEL,CONFIRM:a.CONFIRM},g},g.removeLocale=function(t){return delete v[t],g},g.setLocale=function(t){return g.setDefaults("locale",t)},g.init=function(a){return t(a||e)},g}),function(t,e){"use strict";var a="zui.draggable",i={container:"body",move:!0},o=0,n=function(e,a){var n=this;n.$=t(e),n.id=o++,n.options=t.extend({},i,n.$.data(),a),n.init()};n.DEFAULTS=i,n.NAME=a,n.prototype.init=function(){var i,o,n,s,r,l=this,d=l.$,c="before",p="drag",h="finish",f="."+a+"."+l.id,u="mousedown"+f,g="mouseup"+f,v="mousemove"+f,m=l.options,b=m.selector,y=m.handle,w=d,C=function(t){var e=t.pageX,a=t.pageY;r=!0;var o={left:e-n.x,top:a-n.y};w.removeClass("drag-ready").addClass("dragging"),m.move&&w.css(o),m[p]&&m[p]({event:t,element:w,startOffset:n,pos:o,offset:{x:e-i.x,y:a-i.y},smallOffset:{x:e-s.x,y:a-s.y}}),s.x=e,s.y=a,m.stopPropagation&&t.stopPropagation()},x=function(a){if(t(e).off(f),!r)return void w.removeClass("drag-ready");var o={left:a.pageX-n.x,top:a.pageY-n.y};w.removeClass("drag-ready dragging"),m.move&&w.css(o),m[h]&&m[h]({event:a,element:w,startOffset:n,pos:o,offset:{x:a.pageX-i.x,y:a.pageY-i.y},smallOffset:{x:a.pageX-s.x,y:a.pageY-s.y}}),a.preventDefault(),m.stopPropagation&&a.stopPropagation()},$=function(a){var l=t.zui.getMouseButtonCode(m.mouseButton);if(!(l>-1&&a.button!==l)){var d=t(this);if(b&&(w=y?d.closest(b):d),m[c]){var p=m[c]({event:a,element:w});if(p===!1)return}var h=t(m.container),f=w.offset();o=h.offset(),i={x:a.pageX,y:a.pageY},n={x:a.pageX-f.left+o.left,y:a.pageY-f.top+o.top},s=t.extend({},i),r=!1,w.addClass("drag-ready"),a.preventDefault(),m.stopPropagation&&a.stopPropagation(),t(e).on(v,C).on(g,x)}};y?d.on(u,y,$):b?d.on(u,b,$):d.on(u,$)},n.prototype.destroy=function(){var i="."+a+"."+this.id;this.$.off(i),t(e).off(i),this.$.data(a,null)},t.fn.draggable=function(e){return this.each(function(){var i=t(this),o=i.data(a),s="object"==typeof e&&e;o||i.data(a,o=new n(this,s)),"string"==typeof e&&o[e]()})},t.fn.draggable.Constructor=n}(jQuery,document),function(t){"use strict";function e(e,a){if(e===!1)return e;if(!e)return a;e===!0?e={add:!0,"delete":!0,edit:!0,sort:!0}:"string"==typeof e&&(e=e.split(","));var i;return t.isArray(e)&&(i={},t.each(e,function(e,a){t.isPlainObject(a)?i[a.action]=a:i[a]=!0}),e=i),t.isPlainObject(e)&&(i={},t.each(e,function(e,a){a?i[e]=t.extend({type:e},s[e],t.isPlainObject(a)?a:null):i[e]=!1}),e=i),a?t.extend(!0,{},a,e):e}function a(e,a,i){return a=a||e.type,t(i||e.template).addClass("tree-action").attr(t.extend({"data-type":a,title:e.title||""},e.attr)).data("action",e)}var i="zui.tree",o=0,n=function(e,a){this.name=i,this.$=t(e),this.getOptions(a),this._init()},s={sort:{template:''},add:{template:''},edit:{template:''},"delete":{template:''}};n.DEFAULTS={animate:null,initialState:"normal",toggleTemplate:''},n.prototype.add=function(e,a,i,o,n){var s,r=t(e),l=this.options;if(r.is("li")?(s=r.children("ul"),s.length||(s=t("
          • webhook->paramsList, $webhook->params);?>
            - - - - webhook->objectTypes as $objectType => $actions):?> - - - - - -
            - - actions->$objectType) ? $webhook->actions->$objectType : '');?>
            -
            webhook->desc;?> desc, "rows='3' class='form-control'");?>
            ').append(u))}a.flexStart=-1,a.flexEnd=-1,i=a.cols,a.colsLength=i.length;for(var s=0;s=0,a.fixedRight=a.flexEnd>=0&&a.flexEnd0,a.flexStart<0&&a.flexEnd<0&&(a.fixedLeft=!0,a.flexStart=a.colsLength,a.flexEnd=a.colsLength),this.data=a,this.callEvent("afterLoad",{data:a}),this.render()},i.prototype.render=function(){var a,i,o,n,s=this,r=s.$datatable||(s.isTable?t('
            '):s.$datatable),l=s.options,d=s.data,c=s.data.cols,p=s.data.rows,h=l.checkable,f='
            ',u='
            ';r.children(".datatable-head, .datatable-rows, .scroll-wrapper").remove(),r.toggleClass("sortable",l.sortable);var g,v,m,b=t('
            ');for(a=t(""),o=t(""),n=t(""),i=0;i=d.flexStart&&i<=d.flexEnd?n:o,0===i&&h&&g.append(''),m.ignore||(v=t(""),v.toggleClass("sort-down","down"===m.sort).toggleClass("sort-up","up"===m.sort).toggleClass("sort-disabled",m.sort===!1),v.addClass(m.cssClass).addClass(m.colClass).html(m.text).attr({"data-index":i,"data-type":m.type,style:m.css}).css("width",m.width),g.append(v));var y;d.fixedLeft&&(y=t(u),y.addClass("fixed-left").find("table").addClass(l.tableClass).find("thead").append(a),b.append(y)),d.flexArea&&(y=t(u),y.addClass("flexarea").find(".datatable-wrapper").append('
            ').find("table").addClass(l.tableClass).find("thead").append(n),b.append(y)),d.fixedRight&&(y=t(u),y.addClass("fixed-right").find("table").addClass(l.tableClass).find("thead").append(o),b.append(y)),r.append(b);var w,C,x,$,k,T,E,z,S=t('
            '),D=p.length;a=t(""),o=t(""),n=t("");for(var L=0;L"),w.addClass(T.cssClass).toggleClass(l.checkedClass,!!T.checked).attr({"data-index":L,"data-id":T.id}),C=w.clone(),x=w.clone(),z=T.data.length,i=0;i0&&E.empty||(g=i=d.flexStart&&i<=d.flexEnd?C:x,0===i&&h&&(k=t(''),l.checkboxName&&k.append(''),g.append(k)),c[i].ignore||(t.isPlainObject(E)?(E.row=L,E.index=i):E={text:E,row:L,index:i},T.data[i]=E,$=t(""),$.html(E.text).addClass(E.cssClass).addClass(c[i].colClass).attr("colspan",E.colSpan).attr({"data-row":L,"data-index":i,"data-flex":!1,"data-type":c[i].type,style:E.css,title:E.title||""}).css("width",c[i].width),g.append($)));a.append(w),n.append(C),o.append(x)}var A;d.fixedLeft&&(A=t(f),A.addClass("fixed-left").find("table").addClass(l.tableClass).append(a),S.append(A)),d.flexArea&&(A=t(f),A.addClass("flexarea").find(".datatable-wrapper").append('
            ').find("table").addClass(l.tableClass).append(n),S.append(A)),d.fixedRight&&(A=t(f),A.addClass("fixed-right").find("table").addClass(l.tableClass).append(o),S.append(A)),r.append(S),d.flexArea&&r.append('
            ');var O=r.children(".datatable-footer").detach();d.footer?(r.append(t('