diff --git a/Makefile b/Makefile index 0c1f450754..00a9eb74ce 100644 --- a/Makefile +++ b/Makefile @@ -145,7 +145,7 @@ zentaoxx: sed -i "s/'..\/..\/common\/view\/footer.html.php'/\$$app->getModuleRoot() . 'common\/view\/footer.html.php'/g" zentaoxx/extension/xuan/conference/view/admin.html.php echo "ALTER TABLE \`zt_user\` ADD \`pinyin\` varchar(255) NOT NULL DEFAULT '' AFTER \`realname\`;" >> zentaoxx/db/xuanxuan.sql mkdir zentaoxx/tools; cp tools/cn2tw.php zentaoxx/tools; cd zentaoxx/tools; php cn2tw.php - cp tools/en2de.php zentaoxx/tools; cd zentaoxx/tools; php en2de.php ../ + cp tools/en2other.php zentaoxx/tools; cd zentaoxx/tools; php en2other.php ../ rm -rf zentaoxx/tools #zip -rqm -9 zentaoxx.$(VERSION).zip zentaoxx/* #rm -rf xuan.zip xuan zentaoxx diff --git a/api/v1/entries/user.php b/api/v1/entries/user.php index fef553d697..b4d2dba06e 100644 --- a/api/v1/entries/user.php +++ b/api/v1/entries/user.php @@ -195,7 +195,7 @@ class userEntry extends Entry if(!common::hasPriv('my', 'work')) break; $control = $this->loadController('my', 'task'); - $control->task($this->param('type', 'assignedTo'), $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1)); + $control->task($this->param('type', 'assignedTo'), 0, $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1)); $data = $this->getData(); if($data->status == 'success') diff --git a/config/zentaopms.php b/config/zentaopms.php index 7c03077b46..31d0b2a51b 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -270,6 +270,7 @@ define('TABLE_PROJECTCASE', '`' . $config->db->prefix . 'projectcase`'); define('TABLE_TASKESTIMATE', '`' . $config->db->prefix . 'taskestimate`'); define('TABLE_EFFORT', '`' . $config->db->prefix . 'effort`'); define('TABLE_BURN', '`' . $config->db->prefix . 'burn`'); +define('TABLE_CFD', '`' . $config->db->prefix . 'cfd`'); define('TABLE_BUILD', '`' . $config->db->prefix . 'build`'); define('TABLE_ACL', '`' . $config->db->prefix . 'acl`'); @@ -377,6 +378,8 @@ $config->objectTables['apistruct'] = TABLE_APISTRUCT; $config->newFeatures = array('introduction', 'tutorial', 'youngBlueTheme', 'visions'); +$config->pipelineTypeList = array('gitlab', 'sonarqube', 'jenkins'); + /* Program privs.*/ $config->programPriv = new stdclass(); $config->programPriv->scrum = array('story', 'projectstory', 'projectrelease', 'project', 'execution', 'build', 'bug', 'testcase', 'testreport', 'doc', 'repo', 'meeting', 'stakeholder', 'testtask'); diff --git a/db/standard/zentao17.2.sql b/db/standard/zentao17.2.sql index 1b2405df2f..6fdf543367 100644 --- a/db/standard/zentao17.2.sql +++ b/db/standard/zentao17.2.sql @@ -30,7 +30,7 @@ CREATE TABLE `zt_acl` ( PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; CREATE TABLE `zt_action` ( - `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `id` int(9) unsigned NOT NULL AUTO_INCREMENT, `objectType` varchar(30) NOT NULL DEFAULT '', `objectID` mediumint(8) unsigned NOT NULL DEFAULT '0', `product` text NOT NULL, @@ -1009,7 +1009,7 @@ CREATE TABLE `zt_grouppriv` ( UNIQUE KEY `group` (`group`,`module`,`method`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; CREATE TABLE `zt_history` ( - `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `id` int(9) unsigned NOT NULL AUTO_INCREMENT, `action` mediumint(8) unsigned NOT NULL DEFAULT '0', `field` varchar(30) NOT NULL DEFAULT '', `old` text NOT NULL, @@ -1091,6 +1091,7 @@ CREATE TABLE `zt_im_chat` ( `editedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `lastActiveTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `lastMessage` int(11) unsigned NOT NULL DEFAULT '0', + `lastMessageIndex` int(11) unsigned NOT NULL DEFAULT 0, `dismissDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `pinnedMessages` text NOT NULL, PRIMARY KEY (`id`), @@ -1107,6 +1108,8 @@ CREATE TABLE `zt_im_chat_message_index` ( `tableName` char(64) NOT NULL, `start` int(11) unsigned NOT NULL, `end` int(11) unsigned NOT NULL, + `startIndex` int(11) unsigned NOT NULL, + `endIndex` int(11) unsigned NOT NULL, `startDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `endDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `count` mediumint(8) unsigned NOT NULL, @@ -1115,7 +1118,9 @@ CREATE TABLE `zt_im_chat_message_index` ( KEY `start` (`start`), KEY `end` (`end`), KEY `startDate` (`startDate`), - KEY `endDate` (`endDate`) + KEY `endDate` (`endDate`), + KEY `chatstartindex` (`gid`,`startIndex`), + KEY `chatendindex` (`gid`,`endIndex`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; CREATE TABLE `zt_im_chatuser` ( `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, @@ -1130,6 +1135,7 @@ CREATE TABLE `zt_im_chatuser` ( `quit` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `category` varchar(40) NOT NULL DEFAULT '', `lastReadMessage` int(11) unsigned NOT NULL DEFAULT '0', + `lastReadMessageIndex` int(11) unsigned NOT NULL DEFAULT 0, PRIMARY KEY (`id`), UNIQUE KEY `chatuser` (`cgid`,`user`), KEY `cgid` (`cgid`), @@ -1179,6 +1185,7 @@ CREATE TABLE `zt_im_message` ( `cgid` char(40) NOT NULL DEFAULT '', `user` varchar(30) NOT NULL DEFAULT '', `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `index` int(11) unsigned NOT NULL DEFAULT 0, `type` enum('normal','broadcast','notify','bulletin') NOT NULL DEFAULT 'normal', `content` text NOT NULL, `contentType` enum('text','plain','emotion','image','file','object','code') NOT NULL DEFAULT 'text', @@ -1196,6 +1203,7 @@ CREATE TABLE `zt_im_message_backup` ( `cgid` char(40) NOT NULL DEFAULT '', `user` varchar(30) NOT NULL DEFAULT '', `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `index` int(11) unsigned NOT NULL DEFAULT 0, `type` enum('normal','broadcast','notify') NOT NULL DEFAULT 'normal', `content` text NOT NULL, `contentType` enum('text','plain','emotion','image','file','object','code') NOT NULL DEFAULT 'text', @@ -2560,6 +2568,8 @@ CREATE TABLE `zt_story` ( `approvedDate` date NOT NULL, `lastEditedBy` varchar(30) NOT NULL DEFAULT '', `lastEditedDate` datetime NOT NULL, + `changedBy` VARCHAR(30) NOT NULL, + `changedDate` DATETIME NOT NULL, `reviewedBy` varchar(255) NOT NULL, `reviewedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `closedBy` varchar(30) NOT NULL DEFAULT '', @@ -3180,6 +3190,7 @@ CREATE TABLE `zt_workflowaction` ( `show` enum('dropdownlist','direct') NOT NULL DEFAULT 'dropdownlist', `order` smallint(5) unsigned NOT NULL, `buildin` tinyint(1) unsigned NOT NULL, + `role` varchar(10) NOT NULL DEFAULT 'custom', `virtual` tinyint(1) unsigned NOT NULL, `conditions` text NOT NULL, `verifications` text NOT NULL, @@ -3241,6 +3252,7 @@ CREATE TABLE `zt_workflowfield` ( `isValue` enum('0','1') NOT NULL DEFAULT '0', `readonly` enum('0','1') NOT NULL DEFAULT '0', `buildin` tinyint(1) unsigned NOT NULL, + `role` varchar(10) NOT NULL DEFAULT 'custom', `desc` text NOT NULL, `createdBy` varchar(30) NOT NULL, `createdDate` datetime NOT NULL, @@ -3262,6 +3274,7 @@ CREATE TABLE `zt_workflowlabel` ( `orderBy` text NOT NULL, `order` tinyint(3) NOT NULL, `buildin` tinyint(1) unsigned NOT NULL, + `role` varchar(10) NOT NULL DEFAULT 'custom', `createdBy` char(30) NOT NULL, `createdDate` datetime NOT NULL, `editedBy` char(30) NOT NULL, diff --git a/db/update17.1.sql b/db/update17.1.sql index 15d43d1d73..cacf357ed6 100644 --- a/db/update17.1.sql +++ b/db/update17.1.sql @@ -18,4 +18,21 @@ ALTER TABLE `zt_kanban` ADD `showWIP` enum('0','1') NOT NULL DEFAULT '1' AFTER ` ALTER TABLE `zt_kanban` ADD `alignment` varchar(10) NOT NULL DEFAULT 'center' AFTER `object`; ALTER TABLE `zt_module` ADD `from` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `type`; -ALTER TABLE `zt_workflow` ADD `approval` enum('enabled', 'disabled') NOT NULL DEFAULT 'disabled' AFTER `status`; \ No newline at end of file + +ALTER TABLE `zt_story` ADD `changedBy` VARCHAR(30) NOT NULL AFTER `lastEditedDate`; +ALTER TABLE `zt_story` ADD `changedDate` DATETIME NOT NULL AFTER `changedBy`; + +ALTER TABLE `zt_action` CHANGE `id` `id` int(9) unsigned NOT NULL AUTO_INCREMENT FIRST; +ALTER TABLE `zt_history` CHANGE `id` `id` int(9) unsigned NOT NULL AUTO_INCREMENT FIRST; + +ALTER TABLE `zt_workflow` ADD `approval` enum('enabled', 'disabled') NOT NULL DEFAULT 'disabled' AFTER `status`; +ALTER TABLE `zt_workflowaction` ADD `role` varchar(10) NOT NULL DEFAULT 'custom' AFTER `buildin`; +ALTER TABLE `zt_workflowfield` ADD `role` varchar(10) NOT NULL DEFAULT 'custom' AFTER `buildin`; +ALTER TABLE `zt_workflowlabel` ADD `role` varchar(10) NOT NULL DEFAULT 'custom' AFTER `buildin`; + +UPDATE `zt_workflowaction` SET `role` = 'buildin' WHERE `role` = 'custom' AND `buildin` = '1'; +UPDATE `zt_workflowaction` SET `role` = 'virtual' WHERE `role` = 'custom' AND `virtual` = '1'; +UPDATE `zt_workflowaction` SET `role` = 'default' WHERE `role` = 'custom' AND `action` IN ('browse', 'create', 'batchcreate', 'edit', 'view', 'delete', 'link', 'unlink', 'export', 'exporttemplate', 'import', 'showimport', 'report', 'assign', 'batchedit', 'batchassign'); +UPDATE `zt_workflowfield` SET `role` = 'buildin' WHERE `role` = 'custom' AND (`buildin` = '1' OR `field` = 'subStatus'); +UPDATE `zt_workflowfield` SET `role` = 'default' WHERE `role` = 'custom' AND `field` IN ('id', 'parent', 'assignedTo', 'status', 'createdBy', 'createdDate', 'editedBy', 'editedDate', 'assignedBy', 'assignedDate' 'mailto', 'deleted'); +UPDATE `zt_workflowlabel` SET `role` = 'buildin' WHERE `role` = 'custom' AND `buildin` = '1'; diff --git a/db/update17.2.sql b/db/update17.2.sql new file mode 100644 index 0000000000..f0eef2d504 --- /dev/null +++ b/db/update17.2.sql @@ -0,0 +1,11 @@ +CREATE TABLE `zt_cfd` ( + `id` int(8) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `execution` int(8) NOT NULL, + `type` char(30) NOT NULL, + `name` char(30) NOT NULL, + `count` smallint NOT NULL, + `date` date NOT NULL, + UNIQUE KEY `execution_type_name_date` (`execution`,`type`,`name`,`date`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`, `lastTime`) VALUES ('30', '23', '*', '*', '*', 'moduleName=execution&methodName=computecfd', '更新累积流图', 'zentao', 1, 'normal', '0000-00-00 00:00:00'); diff --git a/db/zentao.sql b/db/zentao.sql index f5aba4dff7..980a637e0b 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -10,7 +10,7 @@ CREATE TABLE IF NOT EXISTS `zt_acl` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_action`; CREATE TABLE IF NOT EXISTS `zt_action` ( - `id` mediumint(8) unsigned NOT NULL auto_increment, + `id` int(9) unsigned NOT NULL auto_increment, `objectType` varchar(30) NOT NULL default '', `objectID` mediumint(8) unsigned NOT NULL default '0', `product` text NOT NULL, @@ -411,6 +411,16 @@ CREATE TABLE IF NOT EXISTS `zt_casestep` ( KEY `case` (`case`), KEY `version` (`version`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; +-- DROP TABLE IF EXISTS `zt_cfd`; +CREATE TABLE `zt_cfd` ( + `id` int(8) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `execution` int(8) NOT NULL, + `type` char(30) NOT NULL, + `name` char(30) NOT NULL, + `count` smallint NOT NULL, + `date` date NOT NULL, + UNIQUE KEY `execution_type_name_date` (`execution`,`type`,`name`,`date`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_company`; CREATE TABLE IF NOT EXISTS `zt_company` ( `id` mediumint(8) unsigned NOT NULL auto_increment, @@ -705,7 +715,7 @@ CREATE TABLE IF NOT EXISTS `zt_holiday` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_history`; CREATE TABLE IF NOT EXISTS `zt_history` ( - `id` mediumint(8) unsigned NOT NULL auto_increment, + `id` int(9) unsigned NOT NULL auto_increment, `action` mediumint(8) unsigned NOT NULL default '0', `field` varchar(30) NOT NULL default '', `old` text NOT NULL, @@ -1397,6 +1407,8 @@ CREATE TABLE IF NOT EXISTS `zt_story` ( `assignedDate` datetime NOT NULL, `lastEditedBy` varchar(30) NOT NULL default '', `lastEditedDate` datetime NOT NULL, + `changedBy` VARCHAR(30) NOT NULL, + `changedDate` DATETIME NOT NULL, `reviewedBy` varchar(255) NOT NULL, `reviewedDate` datetime NOT NULL default '0000-00-00 00:00:00', `closedBy` varchar(30) NOT NULL default '', @@ -1830,7 +1842,8 @@ CREATE TABLE IF NOT EXISTS `zt_webhook` ( INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`, `lastTime`) VALUES ('*', '*', '*', '*', '*', '', '监控定时任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), -('30', '23', '*', '*', '*', 'moduleName=execution&methodName=computeburn', '更新燃尽图', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), +('30', '23', '*', '*', '*', 'moduleName=execution&methodName=computeburn', '更新燃尽图', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), +('30', '23', '*', '*', '*', 'moduleName=execution&methodName=computecfd', '更新累积流图', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), ('0', '8', '*', '*', '*', 'moduleName=report&methodName=remind', '每日任务提醒', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), ('*/5', '*', '*', '*', '*', 'moduleName=svn&methodName=run', '同步SVN', 'zentao', 1, 'stop', '0000-00-00 00:00:00'), ('*/5', '*', '*', '*', '*', 'moduleName=git&methodName=run', '同步GIT', 'zentao', 1, 'stop', '0000-00-00 00:00:00'), @@ -6140,6 +6153,7 @@ CREATE TABLE IF NOT EXISTS `zt_im_chat` ( `mergedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `lastActiveTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `lastMessage` int(11) unsigned NOT NULL DEFAULT 0, + `lastMessageIndex` int(11) unsigned NOT NULL DEFAULT 0, `dismissDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `pinnedMessages` text NOT NULL DEFAULT '', `mergedChats` text NOT NULL DEFAULT '', @@ -6166,6 +6180,7 @@ CREATE TABLE IF NOT EXISTS `zt_im_chatuser` ( `quit` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `category` varchar(40) NOT NULL DEFAULT '', `lastReadMessage` int(11) unsigned NOT NULL DEFAULT 0, + `lastReadMessageIndex` int(11) unsigned NOT NULL DEFAULT 0, PRIMARY KEY (`id`), KEY `cgid` (`cgid`), KEY `user` (`user`), @@ -6198,6 +6213,7 @@ CREATE TABLE IF NOT EXISTS `zt_im_message` ( `cgid` char(40) NOT NULL DEFAULT '', `user` varchar(30) NOT NULL DEFAULT '', `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `index` int(11) unsigned NOT NULL DEFAULT 0, `type` enum('normal', 'broadcast', 'notify', 'bulletin') NOT NULL DEFAULT 'normal', `content` text NOT NULL DEFAULT '', `contentType` enum('text', 'plain', 'emotion', 'image', 'file', 'object', 'code') NOT NULL DEFAULT 'text', @@ -6217,6 +6233,7 @@ CREATE TABLE IF NOT EXISTS `zt_im_message_backup` ( `cgid` char(40) NOT NULL DEFAULT '', `user` varchar(30) NOT NULL DEFAULT '', `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `index` int(11) unsigned NOT NULL DEFAULT 0, `type` enum('normal', 'broadcast', 'notify') NOT NULL DEFAULT 'normal', `content` text NOT NULL DEFAULT '', `contentType` enum('text', 'plain', 'emotion', 'image', 'file', 'object', 'code') NOT NULL DEFAULT 'text', @@ -6248,6 +6265,8 @@ CREATE TABLE IF NOT EXISTS `zt_im_chat_message_index` ( `tableName` char(64) NOT NULL, `start` int(11) unsigned NOT NULL, `end` int(11) unsigned NOT NULL, + `startIndex` int(11) unsigned NOT NULL, + `endIndex` int(11) unsigned NOT NULL, `startDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `endDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `count` mediumint(8) unsigned NOT NULL, @@ -6256,7 +6275,9 @@ CREATE TABLE IF NOT EXISTS `zt_im_chat_message_index` ( KEY `start` (`start`), KEY `end` (`end`), KEY `startDate` (`startDate`), - KEY `endDate` (`endDate`) + KEY `endDate` (`endDate`), + KEY `chatstartindex` (`gid`,`startIndex`), + KEY `chatendindex` (`gid`,`endIndex`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_im_messagestatus`; @@ -8524,6 +8545,7 @@ CREATE TABLE IF NOT EXISTS `zt_workflowaction` ( `show` enum('dropdownlist', 'direct') NOT NULL DEFAULT 'dropdownlist', `order` smallint(5) unsigned NOT NULL, `buildin` tinyint(1) unsigned NOT NULL, + `role` varchar(10) NOT NULL DEFAULT 'custom', `virtual` tinyint(1) unsigned NOT NULL, `conditions` text NOT NULL, `verifications` text NOT NULL, @@ -8587,6 +8609,7 @@ CREATE TABLE IF NOT EXISTS `zt_workflowfield` ( `isValue` enum('0', '1') NOT NULL DEFAULT '0', `readonly` enum('0', '1') NOT NULL DEFAULT '0', `buildin` tinyint(1) unsigned NOT NULL, + `role` varchar(10) NOT NULL DEFAULT 'custom', `desc` text NOT NULL, `createdBy` varchar(30) NOT NULL, `createdDate` datetime NOT NULL, @@ -8631,6 +8654,7 @@ CREATE TABLE IF NOT EXISTS `zt_workflowlabel` ( `orderBy` text NOT NULL, `order` tinyint(3) NOT NULL, `buildin` tinyint(1) unsigned NOT NULL, + `role` varchar(10) NOT NULL DEFAULT 'custom', `createdBy` char(30) NOT NULL, `createdDate` datetime NOT NULL, `editedBy` char(30) NOT NULL, @@ -13480,12 +13504,7 @@ REPLACE INTO `zt_zoutput` (`id`, `activity`, `name`, `content`, `optional`, `tai (246, 163, '《配置审计报告》', '', 'yes', '', '', 'admin', '2020-01-09 14:55:08', '', '0000-00-00 00:00:00', 605, '0'), (247, 166, '《度量分析计划》', '', 'yes', '', '', 'admin', '2020-01-09 14:55:08', '', '0000-00-00 00:00:00', 610, '0'), (248, 168, '项目度量数据库', '', 'yes', '', '', 'admin', '2020-01-09 14:55:08', '', '0000-00-00 00:00:00', 615, '0'), -(249, 172, '《量化项目管理及跟踪计划》', '', 'no', '', '', 'admin', '2020-01-09 14:59:04', '', '0000-00-00 00:00:00', 620, '0'), -(250, 170, '《决策分析报告》的决策分析评估表', '', 'no', '', '', 'admin', '2020-01-09 14:59:04', '', '0000-00-00 00:00:00', 625, '0'), -(251, 169, '《量化项目计划及跟踪表》', '', 'no', '', '', 'admin', '2020-01-09 14:59:04', '', '0000-00-00 00:00:00', 630, '0'), -(252, 173, '《决策分析报告》的评分表', '', 'no', '', '', 'admin', '2020-01-09 14:59:04', '', '0000-00-00 00:00:00', 635, '0'), -(253, 174, '《决策分析报告》的评分表', '', 'no', '', '', 'admin', '2020-01-09 14:59:04', '', '0000-00-00 00:00:00', 640, '0'), -(254, 175, '《决策分析报告》', '', 'no', '', '', 'admin', '2020-01-09 14:59:04', '', '0000-00-00 00:00:00', 645, '0'); +(249, 169, '《量化项目计划及跟踪表》', '', 'no', '', '', 'admin', '2020-01-09 14:59:04', '', '0000-00-00 00:00:00', 630, '0'); REPLACE INTO `zt_basicmeas` VALUES (2,'scale','project','userRequest','项目用户需求初始规模','pgmURInitScale','故事点或功能点','CREATE FUNCTION qc_pgmurinitscale($project int) returns float (10,2)\r\nbegin\r\n declare scale float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'URS\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_initscale($project, \'URS\',\'requestEst\') into scale__DELIMITER__\r\n return scale__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nend','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目每个产品的第一个用户需求规格说明书基线版本的规模之和','从基线表中查询该项目下面每个产品的第一个用户需求规模说明书版本,然后查询对应的需求,求和。','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','system','0000-00-00 00:00:00','admin','2020-07-07 14:19:41',10,'0'), diff --git a/extension/lite/action/ext/lang/de/lite.php b/extension/lite/action/ext/lang/de/lite.php index fb0fcbad1b..954a91a744 100644 --- a/extension/lite/action/ext/lang/de/lite.php +++ b/extension/lite/action/ext/lang/de/lite.php @@ -59,9 +59,9 @@ $lang->action->dynamicAction->task['linkchildtask'] = 'Link child Task'; $lang->action->label->createchildrenstory = "Create child story"; $lang->action->label->linkchildstory = "Link child story"; -$lang->action->label->unlinkchildrenstory = "CanceledLink child story"; +$lang->action->label->unlinkchildrenstory = "unlinked a child story"; $lang->action->label->linkparentstory = "Link parent story"; -$lang->action->label->unlinkparentstory = "From parent storyCanceledLink"; +$lang->action->label->unlinkparentstory = "CanceledLink from parent story "; $lang->action->label->deletechildrenstory = "Deleted child story"; $lang->action->search->label = array(); @@ -101,13 +101,6 @@ $lang->action->search->label['verified'] = $lang->action->label->ve $lang->action->search->label['login'] = $lang->action->label->login; $lang->action->search->label['logout'] = $lang->action->label->logout; -$lang->action->label->createchildrenstory = "Create child story"; -$lang->action->label->linkchildstory = "Link child story"; -$lang->action->label->unlinkchildrenstory = "unlinked a child story"; -$lang->action->label->linkparentstory = "Link parent story"; -$lang->action->label->unlinkparentstory = "CanceledLink from parent story "; -$lang->action->label->deletechildrenstory = "Deleted child story"; - $lang->action->desc->createchildrenstory = '$date, $actor Create child story $extra。' . "\n"; $lang->action->desc->linkchildstory = '$date, $actor Link child story $extra。' . "\n"; $lang->action->desc->unlinkchildrenstory = '$date, $actor Unlink child story $extra。' . "\n"; diff --git a/extension/lite/action/ext/lang/en/lite.php b/extension/lite/action/ext/lang/en/lite.php index fb0fcbad1b..954a91a744 100644 --- a/extension/lite/action/ext/lang/en/lite.php +++ b/extension/lite/action/ext/lang/en/lite.php @@ -59,9 +59,9 @@ $lang->action->dynamicAction->task['linkchildtask'] = 'Link child Task'; $lang->action->label->createchildrenstory = "Create child story"; $lang->action->label->linkchildstory = "Link child story"; -$lang->action->label->unlinkchildrenstory = "CanceledLink child story"; +$lang->action->label->unlinkchildrenstory = "unlinked a child story"; $lang->action->label->linkparentstory = "Link parent story"; -$lang->action->label->unlinkparentstory = "From parent storyCanceledLink"; +$lang->action->label->unlinkparentstory = "CanceledLink from parent story "; $lang->action->label->deletechildrenstory = "Deleted child story"; $lang->action->search->label = array(); @@ -101,13 +101,6 @@ $lang->action->search->label['verified'] = $lang->action->label->ve $lang->action->search->label['login'] = $lang->action->label->login; $lang->action->search->label['logout'] = $lang->action->label->logout; -$lang->action->label->createchildrenstory = "Create child story"; -$lang->action->label->linkchildstory = "Link child story"; -$lang->action->label->unlinkchildrenstory = "unlinked a child story"; -$lang->action->label->linkparentstory = "Link parent story"; -$lang->action->label->unlinkparentstory = "CanceledLink from parent story "; -$lang->action->label->deletechildrenstory = "Deleted child story"; - $lang->action->desc->createchildrenstory = '$date, $actor Create child story $extra。' . "\n"; $lang->action->desc->linkchildstory = '$date, $actor Link child story $extra。' . "\n"; $lang->action->desc->unlinkchildrenstory = '$date, $actor Unlink child story $extra。' . "\n"; diff --git a/extension/lite/action/ext/lang/fr/lite.php b/extension/lite/action/ext/lang/fr/lite.php index fb0fcbad1b..954a91a744 100644 --- a/extension/lite/action/ext/lang/fr/lite.php +++ b/extension/lite/action/ext/lang/fr/lite.php @@ -59,9 +59,9 @@ $lang->action->dynamicAction->task['linkchildtask'] = 'Link child Task'; $lang->action->label->createchildrenstory = "Create child story"; $lang->action->label->linkchildstory = "Link child story"; -$lang->action->label->unlinkchildrenstory = "CanceledLink child story"; +$lang->action->label->unlinkchildrenstory = "unlinked a child story"; $lang->action->label->linkparentstory = "Link parent story"; -$lang->action->label->unlinkparentstory = "From parent storyCanceledLink"; +$lang->action->label->unlinkparentstory = "CanceledLink from parent story "; $lang->action->label->deletechildrenstory = "Deleted child story"; $lang->action->search->label = array(); @@ -101,13 +101,6 @@ $lang->action->search->label['verified'] = $lang->action->label->ve $lang->action->search->label['login'] = $lang->action->label->login; $lang->action->search->label['logout'] = $lang->action->label->logout; -$lang->action->label->createchildrenstory = "Create child story"; -$lang->action->label->linkchildstory = "Link child story"; -$lang->action->label->unlinkchildrenstory = "unlinked a child story"; -$lang->action->label->linkparentstory = "Link parent story"; -$lang->action->label->unlinkparentstory = "CanceledLink from parent story "; -$lang->action->label->deletechildrenstory = "Deleted child story"; - $lang->action->desc->createchildrenstory = '$date, $actor Create child story $extra。' . "\n"; $lang->action->desc->linkchildstory = '$date, $actor Link child story $extra。' . "\n"; $lang->action->desc->unlinkchildrenstory = '$date, $actor Unlink child story $extra。' . "\n"; diff --git a/extension/lite/action/ext/lang/zh-cn/lite.php b/extension/lite/action/ext/lang/zh-cn/lite.php index 7c12ffc960..e350a4d18e 100644 --- a/extension/lite/action/ext/lang/zh-cn/lite.php +++ b/extension/lite/action/ext/lang/zh-cn/lite.php @@ -101,13 +101,6 @@ $lang->action->search->label['verified'] = $lang->action->label->ve $lang->action->search->label['login'] = $lang->action->label->login; $lang->action->search->label['logout'] = $lang->action->label->logout; -$lang->action->label->createchildrenstory = "创建子目标"; -$lang->action->label->linkchildstory = "关联子目标"; -$lang->action->label->unlinkchildrenstory = "取消关联子目标"; -$lang->action->label->linkparentstory = "关联到父目标"; -$lang->action->label->unlinkparentstory = "从父目标取消关联"; -$lang->action->label->deletechildrenstory = "删除子目标"; - $lang->action->desc->createchildrenstory = '$date, 由 $actor 创建子目标 $extra。' . "\n"; $lang->action->desc->linkchildstory = '$date, 由 $actor 关联子目标 $extra。' . "\n"; $lang->action->desc->unlinkchildrenstory = '$date, 由 $actor 移除子目标 $extra。' . "\n"; diff --git a/extension/lite/attend/ext/view/stat.oa.html.hook.php b/extension/lite/attend/ext/view/stat.oa.html.hook.php deleted file mode 100644 index c5c67c3735..0000000000 --- a/extension/lite/attend/ext/view/stat.oa.html.hook.php +++ /dev/null @@ -1,3 +0,0 @@ -getExtensionRoot() . '/biz/attend/ext/view/stat.oa.html.hook.php'; -?> \ No newline at end of file diff --git a/extension/lite/block/ext/view/printassigntomeblock.lite.html.hook.php b/extension/lite/block/ext/view/printassigntomeblock.lite.html.hook.php index d0992c9834..ddfa6fcaa1 100644 --- a/extension/lite/block/ext/view/printassigntomeblock.lite.html.hook.php +++ b/extension/lite/block/ext/view/printassigntomeblock.lite.html.hook.php @@ -1,3 +1,3 @@ diff --git a/extension/lite/custom/ext/lang/de/lite.php b/extension/lite/custom/ext/lang/de/lite.php index adc8835faf..7b4a6e67f3 100644 --- a/extension/lite/custom/ext/lang/de/lite.php +++ b/extension/lite/custom/ext/lang/de/lite.php @@ -13,6 +13,14 @@ $lang->custom->object['todo'] = 'Todo'; $lang->custom->object['user'] = 'User'; $lang->custom->object['block'] = 'Block'; +$lang->custom->menuOrder = array(); +$lang->custom->menuOrder[10] = 'execution'; +$lang->custom->menuOrder[15] = 'story'; +$lang->custom->menuOrder[20] = 'task'; +$lang->custom->menuOrder[25] = 'todo'; +$lang->custom->menuOrder[30] = 'user'; +$lang->custom->menuOrder[35] = 'block'; + $lang->custom->task = new stdClass(); $lang->custom->task->fields['priList'] = 'Priority'; $lang->custom->task->fields['typeList'] = 'Type'; diff --git a/extension/lite/custom/ext/lang/en/lite.php b/extension/lite/custom/ext/lang/en/lite.php index adc8835faf..7b4a6e67f3 100644 --- a/extension/lite/custom/ext/lang/en/lite.php +++ b/extension/lite/custom/ext/lang/en/lite.php @@ -13,6 +13,14 @@ $lang->custom->object['todo'] = 'Todo'; $lang->custom->object['user'] = 'User'; $lang->custom->object['block'] = 'Block'; +$lang->custom->menuOrder = array(); +$lang->custom->menuOrder[10] = 'execution'; +$lang->custom->menuOrder[15] = 'story'; +$lang->custom->menuOrder[20] = 'task'; +$lang->custom->menuOrder[25] = 'todo'; +$lang->custom->menuOrder[30] = 'user'; +$lang->custom->menuOrder[35] = 'block'; + $lang->custom->task = new stdClass(); $lang->custom->task->fields['priList'] = 'Priority'; $lang->custom->task->fields['typeList'] = 'Type'; diff --git a/extension/lite/custom/ext/lang/fr/lite.php b/extension/lite/custom/ext/lang/fr/lite.php index adc8835faf..7b4a6e67f3 100644 --- a/extension/lite/custom/ext/lang/fr/lite.php +++ b/extension/lite/custom/ext/lang/fr/lite.php @@ -13,6 +13,14 @@ $lang->custom->object['todo'] = 'Todo'; $lang->custom->object['user'] = 'User'; $lang->custom->object['block'] = 'Block'; +$lang->custom->menuOrder = array(); +$lang->custom->menuOrder[10] = 'execution'; +$lang->custom->menuOrder[15] = 'story'; +$lang->custom->menuOrder[20] = 'task'; +$lang->custom->menuOrder[25] = 'todo'; +$lang->custom->menuOrder[30] = 'user'; +$lang->custom->menuOrder[35] = 'block'; + $lang->custom->task = new stdClass(); $lang->custom->task->fields['priList'] = 'Priority'; $lang->custom->task->fields['typeList'] = 'Type'; diff --git a/extension/lite/execution/ext/view/create.html.php b/extension/lite/execution/ext/view/create.html.php index 745ad6429e..c39bedc1b0 100644 --- a/extension/lite/execution/ext/view/create.html.php +++ b/extension/lite/execution/ext/view/create.html.php @@ -30,6 +30,7 @@ project->common);?> systemMode);?> +
diff --git a/extension/lite/feedback/ext/view/view.lite.html.hook.php b/extension/lite/feedback/ext/view/view.lite.html.hook.php index 8ad5595c4d..d4ee0a9836 100644 --- a/extension/lite/feedback/ext/view/view.lite.html.hook.php +++ b/extension/lite/feedback/ext/view/view.lite.html.hook.php @@ -1,3 +1,8 @@ diff --git a/extension/lite/flow/ext/view/browse.flow.html.hook.php b/extension/lite/flow/ext/view/browse.flow.html.hook.php deleted file mode 100644 index c66dc67377..0000000000 --- a/extension/lite/flow/ext/view/browse.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/flow/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/flow/ext/view/create.flow.html.hook.php b/extension/lite/flow/ext/view/create.flow.html.hook.php deleted file mode 100644 index c66dc67377..0000000000 --- a/extension/lite/flow/ext/view/create.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/flow/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/group/ext/lang/resource.php b/extension/lite/group/ext/lang/resource.php index de00c3c944..ec5c6714a9 100644 --- a/extension/lite/group/ext/lang/resource.php +++ b/extension/lite/group/ext/lang/resource.php @@ -551,8 +551,8 @@ $lang->resource->task->recordEstimate = 'recordEstimateAction'; $lang->resource->task->editEstimate = 'editEstimate'; $lang->resource->task->deleteEstimate = 'deleteEstimate'; $lang->resource->task->report = 'reportChart'; -$lang->resource->task->exportTemplet = 'exportTemplet'; -$lang->resource->task->import = 'import'; +if($config->edition != 'open') $lang->resource->task->exportTemplet = 'exportTemplet'; +if($config->edition != 'open') $lang->resource->task->import = 'import'; $lang->task->methodOrder[5] = 'create'; $lang->task->methodOrder[10] = 'batchCreate'; diff --git a/extension/lite/project/ext/view/execution.html.php b/extension/lite/project/ext/view/execution.html.php index fc569b5f0d..ced9774f35 100644 --- a/extension/lite/project/ext/view/execution.html.php +++ b/extension/lite/project/ext/view/execution.html.php @@ -30,7 +30,7 @@

execution->noExecution;?> - + createLink('execution', 'create', "projectID=$projectID"), " " . $lang->project->createKanban, '', "class='btn btn-info' data-app='project'");?>

diff --git a/extension/lite/task/ext/view/batchcreate.html.php b/extension/lite/task/ext/view/batchcreate.html.php index a6a4a28c62..17d46ba33a 100644 --- a/extension/lite/task/ext/view/batchcreate.html.php +++ b/extension/lite/task/ext/view/batchcreate.html.php @@ -184,7 +184,7 @@
- +
diff --git a/extension/lite/todo/ext/view/calendar.html.php b/extension/lite/todo/ext/view/calendar.html.php index fd16b01832..90206632a9 100644 --- a/extension/lite/todo/ext/view/calendar.html.php +++ b/extension/lite/todo/ext/view/calendar.html.php @@ -20,6 +20,7 @@ .hide-sidebar #sidebar > .cell {display: none;} .hide-sidebar #sidebar > .sidebar-toggle > .icon:before {content: "\e314";} #date {float: left; margin-right: 10px; margin-left: 0px;} +.cell .nav>li>a:focus {background-color: unset;} lang->side->more);?> todo->moduleList);?> diff --git a/extension/lite/workflow/ext/view/browsedb.flow.html.hook.php b/extension/lite/workflow/ext/view/browsedb.flow.html.hook.php deleted file mode 100644 index 2dbe26bf06..0000000000 --- a/extension/lite/workflow/ext/view/browsedb.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflow/ext/view/browseflow.flow.html.hook.php b/extension/lite/workflow/ext/view/browseflow.flow.html.hook.php deleted file mode 100644 index 2dbe26bf06..0000000000 --- a/extension/lite/workflow/ext/view/browseflow.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflow/ext/view/copy.flow.html.hook.php b/extension/lite/workflow/ext/view/copy.flow.html.hook.php index bb1ebdd750..52a53b968f 100644 --- a/extension/lite/workflow/ext/view/copy.flow.html.hook.php +++ b/extension/lite/workflow/ext/view/copy.flow.html.hook.php @@ -1,4 +1,3 @@ -app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflow/ext/view/create.flow.html.hook.php b/extension/lite/workflow/ext/view/create.flow.html.hook.php index 79974026e4..d7ca3e4619 100644 --- a/extension/lite/workflow/ext/view/create.flow.html.hook.php +++ b/extension/lite/workflow/ext/view/create.flow.html.hook.php @@ -1,3 +1,3 @@ diff --git a/extension/lite/workflow/ext/view/edit.flow.html.hook.php b/extension/lite/workflow/ext/view/edit.flow.html.hook.php deleted file mode 100644 index 2dbe26bf06..0000000000 --- a/extension/lite/workflow/ext/view/edit.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflow/ext/view/flowchart.flow.html.hook.php b/extension/lite/workflow/ext/view/flowchart.flow.html.hook.php deleted file mode 100644 index 2dbe26bf06..0000000000 --- a/extension/lite/workflow/ext/view/flowchart.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflow/ext/view/release.flow.html.hook.php b/extension/lite/workflow/ext/view/release.flow.html.hook.php deleted file mode 100644 index 2dbe26bf06..0000000000 --- a/extension/lite/workflow/ext/view/release.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflow/ext/view/setcss.flow.html.hook.php b/extension/lite/workflow/ext/view/setcss.flow.html.hook.php deleted file mode 100644 index 2dbe26bf06..0000000000 --- a/extension/lite/workflow/ext/view/setcss.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflow/ext/view/setjs.flow.html.hook.php b/extension/lite/workflow/ext/view/setjs.flow.html.hook.php deleted file mode 100644 index 2dbe26bf06..0000000000 --- a/extension/lite/workflow/ext/view/setjs.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflow/ext/view/ui.flow.html.hook.php b/extension/lite/workflow/ext/view/ui.flow.html.hook.php deleted file mode 100644 index 2dbe26bf06..0000000000 --- a/extension/lite/workflow/ext/view/ui.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflowaction/ext/view/browse.flow.html.hook.php b/extension/lite/workflowaction/ext/view/browse.flow.html.hook.php deleted file mode 100644 index 9a25285d22..0000000000 --- a/extension/lite/workflowaction/ext/view/browse.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflowaction/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflowaction/ext/view/create.flow.html.hook.php b/extension/lite/workflowaction/ext/view/create.flow.html.hook.php index 6c51eeb21c..b0f336e568 100644 --- a/extension/lite/workflowaction/ext/view/create.flow.html.hook.php +++ b/extension/lite/workflowaction/ext/view/create.flow.html.hook.php @@ -1,4 +1,3 @@ -app->getExtensionRoot() . 'biz/workflowaction/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflowaction/ext/view/edit.flow.html.hook.php b/extension/lite/workflowaction/ext/view/edit.flow.html.hook.php deleted file mode 100644 index 9a25285d22..0000000000 --- a/extension/lite/workflowaction/ext/view/edit.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflowaction/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflowaction/ext/view/setnotice.flow.html.hook.php b/extension/lite/workflowaction/ext/view/setnotice.flow.html.hook.php deleted file mode 100644 index 9a25285d22..0000000000 --- a/extension/lite/workflowaction/ext/view/setnotice.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflowaction/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflowdatasource/ext/view/edit.flow.html.hook.php b/extension/lite/workflowdatasource/ext/view/edit.flow.html.hook.php deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/extension/lite/workflowfield/ext/view/browse.flow.html.hook.php b/extension/lite/workflowfield/ext/view/browse.flow.html.hook.php deleted file mode 100644 index 11369cc5af..0000000000 --- a/extension/lite/workflowfield/ext/view/browse.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflowfield/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflowfield/ext/view/edit.flow.html.hook.php b/extension/lite/workflowfield/ext/view/edit.flow.html.hook.php index 122e39595d..50342ecd4b 100644 --- a/extension/lite/workflowfield/ext/view/edit.flow.html.hook.php +++ b/extension/lite/workflowfield/ext/view/edit.flow.html.hook.php @@ -1,4 +1,3 @@ -app->getExtensionRoot() . 'biz/workflowfield/ext/view/' . basename(__FILE__);?> visions == ',lite,'):?> dao->select('id')->from(TABLE_WORKFLOWDATASOURCE)->where('code')->like('litefeedback%')->andWhere('vision')->eq('lite')->fetchPairs('id', 'id');?> diff --git a/extension/lite/workflowhook/ext/view/create.flow.html.hook.php b/extension/lite/workflowhook/ext/view/create.flow.html.hook.php deleted file mode 100644 index abebb6d16b..0000000000 --- a/extension/lite/workflowhook/ext/view/create.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflowhook/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflowhook/ext/view/edit.flow.html.hook.php b/extension/lite/workflowhook/ext/view/edit.flow.html.hook.php deleted file mode 100644 index abebb6d16b..0000000000 --- a/extension/lite/workflowhook/ext/view/edit.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflowhook/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflowlabel/ext/view/browse.flow.html.hook.php b/extension/lite/workflowlabel/ext/view/browse.flow.html.hook.php deleted file mode 100644 index d32409775c..0000000000 --- a/extension/lite/workflowlabel/ext/view/browse.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflowlabel/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflowlayout/ext/view/admin.flow.html.hook.php b/extension/lite/workflowlayout/ext/view/admin.flow.html.hook.php deleted file mode 100644 index 038a427205..0000000000 --- a/extension/lite/workflowlayout/ext/view/admin.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflowlayout/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflowrelation/ext/view/admin.flow.html.hook.php b/extension/lite/workflowrelation/ext/view/admin.flow.html.hook.php deleted file mode 100644 index 09020f0aad..0000000000 --- a/extension/lite/workflowrelation/ext/view/admin.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflowrelation/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflowrule/ext/view/browse.flow.html.hook.php b/extension/lite/workflowrule/ext/view/browse.flow.html.hook.php deleted file mode 100644 index 06a563562d..0000000000 --- a/extension/lite/workflowrule/ext/view/browse.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflowrule/ext/view/' . basename(__FILE__);?> diff --git a/extension/lite/workflowrule/ext/view/create.flow.html.hook.php b/extension/lite/workflowrule/ext/view/create.flow.html.hook.php index 87f4a20cbc..44fdc794f7 100644 --- a/extension/lite/workflowrule/ext/view/create.flow.html.hook.php +++ b/extension/lite/workflowrule/ext/view/create.flow.html.hook.php @@ -1,4 +1,4 @@ \ No newline at end of file + diff --git a/extension/lite/workflowrule/ext/view/view.flow.html.hook.php b/extension/lite/workflowrule/ext/view/view.flow.html.hook.php deleted file mode 100644 index 06a563562d..0000000000 --- a/extension/lite/workflowrule/ext/view/view.flow.html.hook.php +++ /dev/null @@ -1 +0,0 @@ -app->getExtensionRoot() . 'biz/workflowrule/ext/view/' . basename(__FILE__);?> diff --git a/framework/base/router.class.php b/framework/base/router.class.php index 03af29a265..d112ebe7f9 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -2831,6 +2831,17 @@ class baseRouter fwrite($fh, "\n"); fclose($fh); } + + /** + * Check app if it is run in a container. + * + * @access public + * @return bool + */ + public function isContainer() + { + return strtolower(getenv('IS_CONTAINER')) == 'true'; + } } /** diff --git a/lib/base/front/front.class.php b/lib/base/front/front.class.php index 4c18838dfb..9afe2605e6 100644 --- a/lib/base/front/front.class.php +++ b/lib/base/front/front.class.php @@ -501,8 +501,6 @@ class baseHTML $gobackList = isset($_COOKIE['goback']) ? json_decode($_COOKIE['goback'], true) : array(); $gobackLink = isset($gobackList[$tab]) ? $gobackList[$tab] : ''; - if(strpos($misc, 'data-app') === false) $misc .= " data-app='" . $tab . "'"; - /* If the link of the referer is not the link of the current page or the link of the index, the cookie and gobackLink will be updated. */ if(!preg_match("/(m=|\/)(index|search|$currentModule)(&f=|-)(index|buildquery|$currentMethod)(&|-|\.)?/", strtolower($refererLink))) { diff --git a/lib/scm/gitrepo.class.php b/lib/scm/gitrepo.class.php index 93261cdcac..2b691eef17 100644 --- a/lib/scm/gitrepo.class.php +++ b/lib/scm/gitrepo.class.php @@ -107,6 +107,12 @@ class GitRepo $cmd = escapeCmd("$this->client tag --sort=taggerdate"); $list = execCmd($cmd . ' 2>&1', 'array', $result); if($result) return array(); + + foreach($list as $key => $tag) + { + if(!$tag) unset($list[$key]); + } + return $list; } @@ -139,7 +145,7 @@ class GitRepo } asort($branches); - $branches = array($defaultBranch => $defaultBranch) + $branches; + if($defaultBranch) $branches = array($defaultBranch => $defaultBranch) + $branches; return $branches; } diff --git a/module/action/model.php b/module/action/model.php index 3df166a917..0a515a7cd4 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -985,9 +985,9 @@ class actionModel extends model } $condition = "((product =',0,' or product=0) AND project = '0' AND execution = 0)"; - if(isset($productCondition)) $condition .= ' OR ' . $productCondition; - if(isset($projectCondition)) $condition .= ' OR ' . $projectCondition; - if(isset($executionCondition)) $condition .= ' OR ' . $executionCondition; + if(!empty($productCondition)) $condition .= ' OR ' . $productCondition; + if(!empty($projectCondition)) $condition .= ' OR ' . $projectCondition; + if(!empty($executionCondition)) $condition .= ' OR ' . $executionCondition; } $actionCondition = $this->getActionCondition(); diff --git a/module/api/control.php b/module/api/control.php index d0d3eff2fa..2601e6e871 100755 --- a/module/api/control.php +++ b/module/api/control.php @@ -251,9 +251,10 @@ class api extends control $id = $this->api->createStruct($data); + if(dao::isError()) return $this->sendError(dao::getError()); + $this->action->create('apistruct', $id, 'Created'); - if(dao::isError()) return $this->sendError(dao::getError()); return $this->sendSuccess(array('locate' => helper::createLink('api', 'struct', "libID=$libID"))); } @@ -455,7 +456,7 @@ class api extends control $this->getTypeOptions($api->lib); $this->view->title = $api->title . $this->lang->api->edit; - $this->view->gobackLink = $this->createLink('api', 'index', "libID={$api->lib}&moduleID={$api->module}"); + $this->view->gobackLink = $this->createLink('api', 'index', "libID={$api->lib}&moduleID={$api->module}&apiID=$apiID"); $this->view->user = $this->app->user->account; $this->view->allUsers = $this->loadModel('user')->getPairs('devfirst|noclosed');; $this->view->moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($api->lib, 'api', $startModuleID = 0); diff --git a/module/api/model.php b/module/api/model.php index 539132b98a..4b121cc395 100644 --- a/module/api/model.php +++ b/module/api/model.php @@ -910,7 +910,7 @@ class apiModel extends model $this->config->api->search['module'] = 'api'; $this->config->api->search['queryID'] = $queryID; $this->config->api->search['actionURL'] = $actionURL; - $this->config->api->search['params']['lib']['values'] = array($lib->id => $lib->name) + array('all' => $this->lang->api->allLibs); + $this->config->api->search['params']['lib']['values'] = (!empty($lib)) ? array($lib->id => $lib->name) + array('all' => $this->lang->api->allLibs) : array('all' => $this->lang->api->allLibs); $this->loadModel('search')->setSearchParams($this->config->api->search); } diff --git a/module/api/view/createlib.html.php b/module/api/view/createlib.html.php index 1699aadaa2..4f29e96290 100644 --- a/module/api/view/createlib.html.php +++ b/module/api/view/createlib.html.php @@ -33,7 +33,8 @@ api->control;?> - api->aclList, 'open', "onchange='toggleAcl(this.value, \"lib\")'")?> + + api->aclList, 'open', "onchange='toggleAcl(this.value, \"lib\")' $isDisabled")?> api->noticeAcl['open'];?> diff --git a/module/block/control.php b/module/block/control.php index 7af7fdf698..ec75a3c39f 100644 --- a/module/block/control.php +++ b/module/block/control.php @@ -1079,10 +1079,10 @@ class block extends control /* Get tasks. Fix bug #2918.*/ $yesterday = date('Y-m-d', strtotime('-1 day')); - $taskGroups = $this->dao->select("id,parent,project,status,finishedDate,estimate,consumed,`left`")->from(TABLE_TASK) - ->where('project')->in($executionIdList) + $taskGroups = $this->dao->select("id,parent,execution,status,finishedDate,estimate,consumed,`left`")->from(TABLE_TASK) + ->where('execution')->in($executionIdList) ->andWhere('deleted')->eq(0) - ->fetchGroup('project', 'id'); + ->fetchGroup('execution', 'id'); $tasks = array(); foreach($taskGroups as $executionID => $taskGroup) @@ -1095,7 +1095,7 @@ class block extends control foreach($taskGroup as $taskID => $task) { - if(strpos('wait|doing|pause', $task->status) !== false) $undoneTasks ++; + if(strpos('wait|doing|pause|cancel', $task->status) !== false) $undoneTasks ++; if(strpos($task->finishedDate, $yesterday) !== false) $yesterdayFinished ++; if($task->parent == '-1') continue; @@ -1131,11 +1131,11 @@ class block extends control } /* Get bugs. */ - $bugs = $this->dao->select("project, count(status) as totalBugs, count(status = 'active' or null) as activeBugs, count(resolvedDate like '{$yesterday}%' or null) as yesterdayResolved")->from(TABLE_BUG) - ->where('project')->in($executionIdList) + $bugs = $this->dao->select("execution, count(status) as totalBugs, count(status = 'active' or null) as activeBugs, count(resolvedDate like '{$yesterday}%' or null) as yesterdayResolved")->from(TABLE_BUG) + ->where('execution')->in($executionIdList) ->andWhere('deleted')->eq(0) - ->groupBy('project') - ->fetchAll('project'); + ->groupBy('execution') + ->fetchAll('execution'); foreach($bugs as $executionID => $bug) { @@ -1717,6 +1717,7 @@ class block extends control if(common::hasPriv('risk', 'view') and $this->config->edition == 'max' and $this->config->vision != 'lite') $hasViewPriv['risk'] = true; if(common::hasPriv('issue', 'view') and $this->config->edition == 'max' and $this->config->vision != 'lite') $hasViewPriv['issue'] = true; if(common::hasPriv('meeting', 'view') and $this->config->edition == 'max' and $this->config->vision != 'lite') $hasViewPriv['meeting'] = true; + if(common::hasPriv('feedback', 'view') and in_array($this->config->edition, array('max', 'biz'))) $hasViewPriv['feedback'] = true; $params = $this->get->param; $params = json_decode(base64_decode($params)); @@ -1725,8 +1726,14 @@ class block extends control $objectCountList = array('todo' => 'todoCount', 'task' => 'taskCount', 'bug' => 'bugCount', 'story' => 'storyCount', 'requirement' => 'requirementCount'); if($this->config->edition == 'max') { - $objectList += array('risk' => 'risks', 'issue' => 'issues'); - $objectCountList += array('risk' => 'riskCount', 'issue' => 'issueCount'); + $objectList += array('risk' => 'risks', 'issue' => 'issues', 'feedback' => 'feedbacks'); + $objectCountList += array('risk' => 'riskCount', 'issue' => 'issueCount', 'feedback' => 'feedbackCount'); + } + + if($this->config->edition == 'biz') + { + $objectList += array('feedback' => 'feedbacks'); + $objectCountList += array('feedback' => 'feedbackCount'); } $tasks = $this->loadModel('task')->getUserSuspendedTasks($this->app->user->account); @@ -1749,6 +1756,10 @@ class block extends control ->beginIF($objectType == 'story' or $objectType == 'requirement')->andWhere('t2.deleted')->eq('0')->fi() ->beginIF($objectType == 'todo')->andWhere('t1.cycle')->eq(0)->andWhere('t1.status')->eq('wait')->andWhere('t1.vision')->eq($this->config->vision)->fi() ->beginIF($objectType != 'todo')->andWhere('t1.status')->ne('closed')->fi() + ->beginIF($objectType == 'feedback') + ->andWhere('t1.status')->in('wait, noreview') + ->andWhere('t1.assignedTo')->eq($this->app->user->account) + ->fi() ->orderBy($orderBy) ->beginIF($limitCount)->limit($limitCount)->fi() ->fetchAll(); @@ -1787,6 +1798,13 @@ class block extends control if($objectType == 'risk') $this->app->loadLang('risk'); if($objectType == 'issue') $this->app->loadLang('issue'); + if($objectType == 'feedback') + { + $this->app->loadLang('feedback'); + $this->view->users = $this->loadModel('user')->getPairs('all,noletter'); + $this->view->products = $this->loadModel('product')->getPairs(); + } + $count[$objectType] = count($objects); $this->view->{$objectList[$objectType]} = $objects; } diff --git a/module/block/lang/de.php b/module/block/lang/de.php index d53880d985..bc16a941ea 100644 --- a/module/block/lang/de.php +++ b/module/block/lang/de.php @@ -357,6 +357,7 @@ $lang->block->availableBlocks->testtask = 'Testaufgaben'; $lang->block->availableBlocks->risk = 'My Risks'; $lang->block->availableBlocks->issue = 'My Issues'; $lang->block->availableBlocks->meeting = 'My Meetings'; +$lang->block->availableBlocks->feedback = 'My Feedbacks'; if($config->systemMode == 'new') $lang->block->moduleList['project'] = 'Project'; $lang->block->moduleList['product'] = $lang->productCommon; @@ -469,13 +470,14 @@ $lang->block->orderByList->story['status_desc'] = 'Status Absteigend'; $lang->block->orderByList->story['stage_asc'] = 'Phase Aufsteigend'; $lang->block->orderByList->story['stage_desc'] = 'Phase Absteigend'; -$lang->block->todoCount = 'Todos'; -$lang->block->taskCount = 'Aufgaben'; -$lang->block->bugCount = 'Bugs'; -$lang->block->riskCount = 'Risk'; -$lang->block->issueCount = 'Issues'; -$lang->block->storyCount = 'Stories'; -$lang->block->meetingCount = 'Meetings'; +$lang->block->todoCount = 'Todos'; +$lang->block->taskCount = 'Aufgaben'; +$lang->block->bugCount = 'Bugs'; +$lang->block->riskCount = 'Risk'; +$lang->block->issueCount = 'Issues'; +$lang->block->storyCount = 'Stories'; +$lang->block->meetingCount = 'Meetings'; +$lang->block->feedbackCount = 'Feedbacks'; $lang->block->typeList = new stdclass(); diff --git a/module/block/lang/en.php b/module/block/lang/en.php index e7a9e6879d..6d6f7ec078 100644 --- a/module/block/lang/en.php +++ b/module/block/lang/en.php @@ -357,6 +357,7 @@ $lang->block->availableBlocks->testtask = 'Requests'; $lang->block->availableBlocks->risk = 'Risks'; $lang->block->availableBlocks->issue = 'Issues'; $lang->block->availableBlocks->meeting = 'Meetings'; +$lang->block->availableBlocks->feedback = 'My Feedbacks'; if($config->systemMode == 'new') $lang->block->moduleList['project'] = 'Project'; $lang->block->moduleList['product'] = $lang->productCommon; @@ -469,13 +470,14 @@ $lang->block->orderByList->story['status_desc'] = 'Story Status DESC'; $lang->block->orderByList->story['stage_asc'] = 'Story Phase ASC'; $lang->block->orderByList->story['stage_desc'] = 'Story Phase DESC'; -$lang->block->todoCount = 'Todo'; -$lang->block->taskCount = 'Task'; -$lang->block->bugCount = 'Bug'; -$lang->block->riskCount = 'Risk'; -$lang->block->issueCount = 'Issues'; -$lang->block->storyCount = 'Stories'; -$lang->block->meetingCount = 'Meetings'; +$lang->block->todoCount = 'Todo'; +$lang->block->taskCount = 'Task'; +$lang->block->bugCount = 'Bug'; +$lang->block->riskCount = 'Risk'; +$lang->block->issueCount = 'Issues'; +$lang->block->storyCount = 'Stories'; +$lang->block->meetingCount = 'Meetings'; +$lang->block->feedbackCount = 'Feedbacks'; $lang->block->typeList = new stdclass(); diff --git a/module/block/lang/fr.php b/module/block/lang/fr.php index 00205f4564..2b662628c3 100644 --- a/module/block/lang/fr.php +++ b/module/block/lang/fr.php @@ -357,6 +357,7 @@ $lang->block->availableBlocks->testtask = 'Recettes'; $lang->block->availableBlocks->risk = 'My Risks'; $lang->block->availableBlocks->issue = 'My Issues'; $lang->block->availableBlocks->meeting = 'My Meetings'; +$lang->block->availableBlocks->feedback = 'My Feedbacks'; if($config->systemMode == 'new') $lang->block->moduleList['project'] = 'Project'; $lang->block->moduleList['product'] = $lang->productCommon; @@ -469,13 +470,14 @@ $lang->block->orderByList->story['status_desc'] = 'Tri par Statut Story DESC'; $lang->block->orderByList->story['stage_asc'] = 'Tri par Phase Story ASC'; $lang->block->orderByList->story['stage_desc'] = 'Tri par Phase Story DESC'; -$lang->block->todoCount = 'Todo'; -$lang->block->taskCount = 'Task'; -$lang->block->bugCount = 'Bug'; -$lang->block->riskCount = 'Risk'; -$lang->block->issueCount = 'Issues'; -$lang->block->storyCount = 'Stories'; -$lang->block->meetingCount = 'Meetings'; +$lang->block->todoCount = 'Todo'; +$lang->block->taskCount = 'Task'; +$lang->block->bugCount = 'Bug'; +$lang->block->riskCount = 'Risk'; +$lang->block->issueCount = 'Issues'; +$lang->block->storyCount = 'Stories'; +$lang->block->meetingCount = 'Meetings'; +$lang->block->feedbackCount = 'Feedbacks'; $lang->block->typeList = new stdclass(); diff --git a/module/block/lang/vi.php b/module/block/lang/vi.php index f707316e13..84f7d1f3b3 100644 --- a/module/block/lang/vi.php +++ b/module/block/lang/vi.php @@ -319,6 +319,7 @@ $lang->block->availableBlocks->testtask = 'Yêu cầu'; $lang->block->availableBlocks->risk = 'My Risks'; $lang->block->availableBlocks->issue = 'My Issues'; $lang->block->availableBlocks->meeting = 'My Meetings'; +$lang->block->availableBlocks->feedback = 'My Feedbacks'; if($config->systemMode == 'new') $lang->block->moduleList['project'] = 'Project'; $lang->block->moduleList['product'] = $lang->productCommon; @@ -431,13 +432,14 @@ $lang->block->orderByList->story['status_desc'] = 'Tình trạng câu chuyện g $lang->block->orderByList->story['stage_asc'] = 'Giai đoạn câu chuyện tăng dần'; $lang->block->orderByList->story['stage_desc'] = 'Giai đoạn câu chuyện giảm dần'; -$lang->block->todoCount = 'Việc làm'; -$lang->block->taskCount = 'Nhiệm vụ'; -$lang->block->bugCount = 'Bug'; -$lang->block->riskCount = 'Risk'; -$lang->block->issueCount = 'Issues'; -$lang->block->storyCount = 'Stories'; -$lang->block->meetingCount = 'Meetings'; +$lang->block->todoCount = 'Việc làm'; +$lang->block->taskCount = 'Nhiệm vụ'; +$lang->block->bugCount = 'Bug'; +$lang->block->riskCount = 'Risk'; +$lang->block->issueCount = 'Issues'; +$lang->block->storyCount = 'Stories'; +$lang->block->meetingCount = 'Meetings'; +$lang->block->feedbackCount = 'Feedbacks'; $lang->block->typeList = new stdclass(); diff --git a/module/block/lang/zh-cn.php b/module/block/lang/zh-cn.php index dc309f107d..adcf517d1d 100644 --- a/module/block/lang/zh-cn.php +++ b/module/block/lang/zh-cn.php @@ -357,6 +357,7 @@ $lang->block->availableBlocks->testtask = '测试版本列表'; $lang->block->availableBlocks->risk = '风险'; $lang->block->availableBlocks->issue = '问题'; $lang->block->availableBlocks->meeting = '会议'; +$lang->block->availableBlocks->feedback = '反馈'; if($config->systemMode == 'new') $lang->block->moduleList['project'] = '项目'; $lang->block->moduleList['product'] = $lang->productCommon; @@ -469,13 +470,14 @@ $lang->block->orderByList->story['status_desc'] = '状态倒序'; $lang->block->orderByList->story['stage_asc'] = '阶段正序'; $lang->block->orderByList->story['stage_desc'] = '阶段倒序'; -$lang->block->todoCount = '待办数'; -$lang->block->taskCount = '任务数'; -$lang->block->bugCount = 'Bug数'; -$lang->block->riskCount = '风险数'; -$lang->block->issueCount = '问题数'; -$lang->block->storyCount = '需求数'; -$lang->block->meetingCount = '会议数'; +$lang->block->todoCount = '待办数'; +$lang->block->taskCount = '任务数'; +$lang->block->bugCount = 'Bug数'; +$lang->block->riskCount = '风险数'; +$lang->block->issueCount = '问题数'; +$lang->block->storyCount = '需求数'; +$lang->block->meetingCount = '会议数'; +$lang->block->feedbackCount = '反馈数'; $lang->block->typeList = new stdclass(); diff --git a/module/block/lang/zh-tw.php b/module/block/lang/zh-tw.php index d951f32b97..1929912983 100644 --- a/module/block/lang/zh-tw.php +++ b/module/block/lang/zh-tw.php @@ -332,6 +332,7 @@ $lang->block->availableBlocks->testtask = '測試版本列表'; $lang->block->availableBlocks->risk = '我的風險'; $lang->block->availableBlocks->issue = '我的問題'; $lang->block->availableBlocks->meeting = '我的會議'; +$lang->block->availableBlocks->feedback = '我的反饋'; if($config->systemMode == 'new') $lang->block->moduleList['project'] = '項目'; $lang->block->moduleList['product'] = $lang->productCommon; @@ -444,13 +445,14 @@ $lang->block->orderByList->story['status_desc'] = '狀態倒序'; $lang->block->orderByList->story['stage_asc'] = '階段正序'; $lang->block->orderByList->story['stage_desc'] = '階段倒序'; -$lang->block->todoCount = '待辦數'; -$lang->block->taskCount = '任務數'; -$lang->block->bugCount = 'Bug數'; -$lang->block->riskCount = '風險數'; -$lang->block->issueCount = '問題數'; -$lang->block->storyCount = '需求數'; -$lang->block->meetingCount = '會議數'; +$lang->block->todoCount = '待辦數'; +$lang->block->taskCount = '任務數'; +$lang->block->bugCount = 'Bug數'; +$lang->block->riskCount = '風險數'; +$lang->block->issueCount = '問題數'; +$lang->block->storyCount = '需求數'; +$lang->block->meetingCount = '會議數'; +$lang->block->feedbackCount = '反饋數'; $lang->block->typeList = new stdclass(); diff --git a/module/block/model.php b/module/block/model.php index 62fe91b209..1c9b01f470 100644 --- a/module/block/model.php +++ b/module/block/model.php @@ -34,6 +34,7 @@ class blockModel extends model ->setDefault('grid', '4') ->setDefault('source', $source) ->setDefault('block', $type) + ->setDefault('vision', $this->config->vision) ->setDefault('params', array()) ->remove('uid,actionLink,modules,moduleBlock') ->get(); @@ -167,7 +168,7 @@ class blockModel extends model { $data = array(); - $tasks = $this->dao->select('t1.id')->from(TABLE_TASK)->alias('t1') + $tasks = $this->dao->select("count(t1.id) as tasks, count(if(t1.status = 'done', 1, null)) as doneTasks")->from(TABLE_TASK)->alias('t1') ->leftJoin(TABLE_PROJECT)->alias('t2')->on("t1.project = t2.id") ->leftJoin(TABLE_EXECUTION)->alias('t3')->on("t1.execution = t3.id") ->where('t1.assignedTo')->eq($this->app->user->account) @@ -179,9 +180,11 @@ class blockModel extends model ->beginIF(!$this->app->user->admin)->andWhere('t1.execution')->in($this->app->user->view->sprints)->fi() ->beginIF($this->config->vision)->andWhere('t1.vision')->eq($this->config->vision)->fi() ->beginIF($this->config->vision)->andWhere('t3.vision')->eq($this->config->vision)->fi() - ->fetchAll('id'); - $data['tasks'] = isset($tasks) ? count($tasks) : 0; - $data['doneTasks'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_TASK)->where('assignedTo')->eq($this->app->user->account)->andWhere('deleted')->eq(0)->andWhere('status')->eq('done')->fetch('count'); + ->fetch(); + + $data['tasks'] = isset($tasks->tasks) ? $tasks->tasks : 0; + $data['doneTasks'] = isset($tasks->doneTasks) ? $tasks->doneTasks : 0; + $data['bugs'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_BUG) ->where('assignedTo')->eq($this->app->user->account) ->andWhere('deleted')->eq(0) @@ -205,12 +208,17 @@ class blockModel extends model ->fetch('count'); $today = date('Y-m-d'); - $data['delayTask'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_TASK) - ->where('assignedTo')->eq($this->app->user->account) - ->andWhere('status')->in('wait,doing') - ->andWhere('deadline')->ne('0000-00-00') - ->andWhere('deadline')->lt($today) - ->andWhere('deleted')->eq(0) + $data['delayTask'] = (int)$this->dao->select('count(t1.id) AS count')->from(TABLE_TASK)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on("t1.project = t2.id") + ->leftJoin(TABLE_EXECUTION)->alias('t3')->on("t1.execution = t3.id") + ->where('t1.assignedTo')->eq($this->app->user->account) + ->andWhere('(t2.status')->ne('suspended') + ->orWhere('t3.status')->ne('suspended') + ->markRight(1) + ->andWhere('t1.status')->in('wait,doing') + ->andWhere('t1.deadline')->ne('0000-00-00') + ->andWhere('t1.deadline')->lt($today) + ->andWhere('t1.deleted')->eq(0) ->fetch('count'); $data['delayBug'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_BUG) ->where('assignedTo')->eq($this->app->user->account) @@ -773,6 +781,10 @@ class blockModel extends model $params->meetingCount['name'] = $this->lang->block->meetingCount; $params->meetingCount['default'] = 20; $params->meetingCount['control'] = 'input'; + + $params->feedbackCount['name'] = $this->lang->block->feedbackCount; + $params->feedbackCount['default'] = 20; + $params->feedbackCount['control'] = 'input'; } $params->storyCount['name'] = $this->lang->block->storyCount; diff --git a/module/block/view/executionstatisticblock.html.php b/module/block/view/executionstatisticblock.html.php index bc8168dd0c..7a90a10d75 100644 --- a/module/block/view/executionstatisticblock.html.php +++ b/module/block/view/executionstatisticblock.html.php @@ -185,11 +185,11 @@ $(function() - + - +
bug->allBugs;?> :totalBugs) ? 0 : html::a($this->createLink('execution', 'bug', "executionID={$execution->id}&orderBy=status,id_desc&build=0&type=all"), $execution->totalBugs);?>totalBugs) ? 0 : html::a($this->createLink('execution', 'bug', "executionID={$execution->id}&productID=0&orderBy=status,id_desc&build=0&type=all"), $execution->totalBugs);?>
bug->unResolved;?> :activeBugs) ? 0 : html::a($this->createLink('execution', 'bug', "executionID={$execution->id}&orderBy=status,id_desc&build=0&type=unresolved"), $execution->activeBugs);?>activeBugs) ? 0 : html::a($this->createLink('execution', 'bug', "executionID={$execution->id}&productID=0&orderBy=status,id_desc&build=0&type=unresolved"), $execution->activeBugs);?>
diff --git a/module/block/view/feedbackblock.html.php b/module/block/view/feedbackblock.html.php new file mode 100644 index 0000000000..27e0eab546 --- /dev/null +++ b/module/block/view/feedbackblock.html.php @@ -0,0 +1,36 @@ + +
block->emptyTip;?>
+ + +
+ '> + + + + + + + + + + + + + get->entry}'" : ''; + ?> + + + + + + + + + + +
idAB?>feedback->product;?>feedback->title?>feedback->type;?>feedback->openedBy;?>feedback->openedDate;?>
id);?>product);?>createLink('feedback', 'view', "feedbackID=$feedback->id"), $feedback->title, '', "data-app='my'")?>feedback->typeList, $feedback->type)?>openedBy)?>openedDate;?>
+
+ diff --git a/module/block/view/main.html.php b/module/block/view/main.html.php index d90a21d363..debaacd1b0 100644 --- a/module/block/view/main.html.php +++ b/module/block/view/main.html.php @@ -10,6 +10,7 @@ * @link http://www.zentao.pms */ $viewDir = dirname(__FILE__); -$file2Include = file_exists(dirname($viewDir) . "/ext/view/{$code}block.html.php") ? dirname($viewDir) . "/ext/view/{$code}block.html.php" : "{$viewDir}/{$code}block.html.php"; +$extFire = $app->getExtensionRoot() . $config->edition . "/block/ext/view/{$code}block.html.php"; +$file2Include = file_exists($extFire) ? $extFire : "{$viewDir}/{$code}block.html.php"; include $file2Include; ?> diff --git a/module/block/view/productstatisticblock.html.php b/module/block/view/productstatisticblock.html.php index 8da697047a..67e8ca90b2 100644 --- a/module/block/view/productstatisticblock.html.php +++ b/module/block/view/productstatisticblock.html.php @@ -127,10 +127,10 @@ $(function()
SRCommon;?>
stories):?>
stories);?>
- id}&branch=&type=allstory", $lang->story->viewAll . '', '', 'class="btn btn-primary btn-circle btn-icon-right btn-sm"');?> + id}&branch=&type=allstory", $lang->story->viewAll . '', '', 'class="btn btn-primary btn-circle btn-icon-right btn-sm" data-app="product"');?>
0
- id}", '' . $lang->story->create, '', 'class="btn btn-primary btn-circle btn-icon-left btn-sm"');?> + id}", '' . $lang->story->create, '', 'class="btn btn-primary btn-circle btn-icon-left btn-sm" data-app="product"');?>
- id}", " " . $lang->productplan->create, '', "class='btn btn-info'");?> + id}", " " . $lang->productplan->create, '', "class='btn btn-info' data-app='product'");?>
@@ -190,7 +190,7 @@ $(function()
- id}", " " . $lang->release->create, '', "class='btn btn-info'");?> + id}", " " . $lang->release->create, '', "class='btn btn-info' data-app='product'");?>
diff --git a/module/block/view/qastatisticblock.html.php b/module/block/view/qastatisticblock.html.php index 5d4085d837..079d2b14c2 100644 --- a/module/block/view/qastatisticblock.html.php +++ b/module/block/view/qastatisticblock.html.php @@ -13,7 +13,8 @@ .product-info .progress-info {position: absolute; left: 8px; top: 10px; width: 180px; font-size: 12px;} .product-info .type-info {color: #A6AAB8; text-align: center; position: absolute; right: 0; top: 6px; width: 100px;} .product-info .type-value, -.product-info .type-label {font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;} +.product-info .type-label {font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #838A9D;} +.progress-pie .progress-info>small {color: #838A9D;} .product-info .type-value {font-size: 14px;} .product-info .type-value > strong {font-size: 20px; color: #3C4353;} .product-info .actions {position: absolute; left: 10px; top: 14px;} diff --git a/module/block/view/todoblock.html.php b/module/block/view/todoblock.html.php index eafcd55de8..781ccf19d9 100644 --- a/module/block/view/todoblock.html.php +++ b/module/block/view/todoblock.html.php @@ -18,11 +18,11 @@ if(!$selfCall) die(include('./todolist.html.php')); .block-todoes .todoes-input .form-control::-moz-placeholder {font-size: 12px; line-height: 20px; color: #a4a8b6;} .block-todoes .todoes-input .form-control:-ms-input-placeholder {font-size: 12px; line-height: 20px;color: #a4a8b6;} .block-todoes .todoes-input .form-control::placeholder {font-size: 12px; line-height: 20px; color: #a4a8b6;} -.block-todoes .todoes {padding: 0 10px 10px 10px; margin: 0 -20px; max-height: 350px; overflow: auto; overflow-x:hidden} +.block-todoes .todoes {padding: 0 10px 10px 10px; margin: 0 -10px; max-height: 350px; overflow: auto; overflow-x:hidden} .block-todoes .todoes > li {position: relative; padding: 5px 10px 5px 35px; list-style: none; white-space:nowrap; overflow: auto; overflow-x:hidden;} .block-todoes .todoes > li:hover {background-color: #e9f2fb;} .block-todoes .todo-title {padding: 0px;} -.titleBox {max-width: 730px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block;} +.titleBox {max-width: 1440px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block;} .block-todoes .todo-pri {margin: 0 5px;} .block-todoes .todo-time {display: inline-block; padding: 0 5px; font-size: 12px; color: #8e939a; width: 95px; min-width: 95px;} .block-todoes .todo-check {position: absolute; top: 5px; left: 10px; display: block; width: 20px; height: 20px; font-size: 20px; color: transparent; cursor: pointer; background: #fff; border: 2px solid #eee; border-radius: 50%;} diff --git a/module/branch/view/manage.html.php b/module/branch/view/manage.html.php index 749c01b408..8287f4b387 100644 --- a/module/branch/view/manage.html.php +++ b/module/branch/view/manage.html.php @@ -102,15 +102,17 @@ desc;?> id&productID=$productID", $branch, 'list', '', '', "$disabled iframe", true, '', $lang->branch->edit); - if($branch->status == 'active') + if(!$isMain) { - common::printIcon('branch', 'close', "branchID=$branch->id", $branch, 'list', 'off', 'hiddenwin', $disabled); - } - else - { - common::printIcon('branch', 'activate', "branchID=$branch->id", $branch, 'list', 'active', 'hiddenwin', $disabled); + common::printIcon('branch', 'edit', "branchID=$branch->id&productID=$productID", $branch, 'list', '', '', 'iframe', true, '', $lang->branch->edit); + if($branch->status == 'active') + { + common::printIcon('branch', 'close', "branchID=$branch->id", $branch, 'list', 'off', 'hiddenwin'); + } + else + { + common::printIcon('branch', 'activate', "branchID=$branch->id", $branch, 'list', 'active', 'hiddenwin'); + } } ?> diff --git a/module/bug/control.php b/module/bug/control.php index ebd9dad1ea..b0c319c502 100755 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -916,7 +916,7 @@ class bug extends control * @access public * @return void */ - public function edit($bugID, $comment = false, $kanbanGroup = '') + public function edit($bugID, $comment = false, $kanbanGroup = 'default') { if(!empty($_POST)) { @@ -1351,7 +1351,7 @@ class bug extends control * @access public * @return void */ - public function assignTo($bugID, $kanbanGroup = '') + public function assignTo($bugID, $kanbanGroup = 'default') { $bug = $this->bug->getById($bugID); $this->bug->checkBugExecutionPriv($bug); @@ -1397,19 +1397,26 @@ class bug extends control } /* Get assigned to member. */ - if($bug->execution) + if($this->app->tab == 'project' or $this->app->tab == 'execution') { - $users = $this->user->getTeamMemberPairs($bug->execution, 'execution'); - } - elseif($bug->project) - { - $users = $this->loadModel('project')->getTeamMemberPairs($bug->project); + if($bug->execution) + { + $users = $this->user->getTeamMemberPairs($bug->execution, 'execution'); + } + elseif($bug->project) + { + $users = $this->loadModel('project')->getTeamMemberPairs($bug->project); + } + else + { + $users = $this->bug->getProductMemberPairs($bug->product, $bug->branch); + $users = array_filter($users); + if(empty($users)) $users = $this->user->getPairs('devfirst|noclosed'); + } } else { - $users = $this->bug->getProductMemberPairs($bug->product, $bug->branch); - $users = array_filter($users); - if(empty($users)) $users = $this->user->getPairs('devfirst|noclosed'); + $users = $this->user->getPairs('devfirst|noclosed'); } $this->view->title = $this->products[$bug->product] . $this->lang->colon . $this->lang->bug->assignedTo; @@ -2252,6 +2259,13 @@ class bug extends control $bug->steps = str_replace(' ', ' ', $bug->steps); } + $bug->openedDate = !helper::isZeroDate($bug->openedDate) ? $bug->openedDate : ''; + $bug->assignedDate = !helper::isZeroDate($bug->assignedDate) ? $bug->assignedDate : ''; + $bug->resolvedDate = !helper::isZeroDate($bug->resolvedDate) ? $bug->resolvedDate : ''; + $bug->closedDate = !helper::isZeroDate($bug->closedDate) ? $bug->closedDate : ''; + $bug->lastEditedDate = !helper::isZeroDate($bug->lastEditedDate) ? $bug->lastEditedDate : ''; + $bug->deadline = !helper::isZeroDate($bug->deadline) ? $bug->deadline : ''; + /* fill some field with useful value. */ $bug->product = !isset($products[$bug->product]) ? '' : $products[$bug->product] . "(#$bug->product)"; $bug->project = !isset($projects[$bug->project]) ? '' : $projects[$bug->project] . "(#$bug->project)"; diff --git a/module/bug/css/batchcreate.css b/module/bug/css/batchcreate.css index dcfd01218a..eaa1b26799 100644 --- a/module/bug/css/batchcreate.css +++ b/module/bug/css/batchcreate.css @@ -6,3 +6,6 @@ .c-build, .c-browser, .c-keywords {width: 100px;} .c-steps {width: 150px;} .c-pri, .c-severity {width: 80px;} +.c-actions {width: 60px;} +[lang^=de] .c-build, [lang^=fr] .c-build {width: 115px} +@media screen and (max-width: 1366px) {[lang^=de] .c-build, [lang^=fr] .c-build {width: 110px}} diff --git a/module/bug/css/browse.css b/module/bug/css/browse.css index f28860922b..7a2518c139 100644 --- a/module/bug/css/browse.css +++ b/module/bug/css/browse.css @@ -34,3 +34,4 @@ body {margin-bottom: 25px;} .btn-group a.btn-primary {border-right: 1px solid rgba(255,255,255,0.3);} .btn-group button.dropdown-toggle.btn-primary {padding:6px;} #bugForm tbody tr td .label {max-width: 100px; text-overflow: unset;} +[lang^='de'] th.c-confirmed {width: 100px !important;} diff --git a/module/bug/css/create.css b/module/bug/css/create.css index be008fac02..470dd51d77 100644 --- a/module/bug/css/create.css +++ b/module/bug/css/create.css @@ -1,5 +1,9 @@ html[lang='en'] #moduleIdBox .input-group-addon {padding: 5px 23px;} html[lang='en'] #deadlineTd .input-group-addon {padding: 5px 18px;} +html[lang='zh-cn'] #keywordsAddonLabel, .task {width: 77px;} +html[lang='zh-tw'] #keywordsAddonLabel, .task {width: 77px;} +html[lang='fr'] #keywordsAddonLabel, .task {width: 61px;} +html[lang='de'] #keywordsAddonLabel, .task {width: 73px;} .ke-toolbar .ke-outline[data-name='savetemplate'] {display: block;} .ke-outline .ke-icon-savetemplate {background-image: url(theme/default/images/kindeditor/save.gif); background-position: center; width: 56px; height: 20px;} diff --git a/module/bug/css/edit.css b/module/bug/css/edit.css index 7f63e63266..ebd0b1eec4 100644 --- a/module/bug/css/edit.css +++ b/module/bug/css/edit.css @@ -6,3 +6,4 @@ #linkBugBox > li {margin-left: -56px;} #branch {width: 95px;} #storyIdBox .chosen-auto-max-width {width: 215px !important;} +.form-group {margin-left: 10px; margin-right: 10px;} diff --git a/module/bug/js/batchcreate.js b/module/bug/js/batchcreate.js index ca5552b022..07d1e30920 100644 --- a/module/bug/js/batchcreate.js +++ b/module/bug/js/batchcreate.js @@ -4,8 +4,95 @@ $(function() var $titleCol = $('#batchCreateForm table thead tr th.c-title'); if($titleCol.width() < 150) $titleCol.width(150); + + $('#customField').click(function() + { + hiddenRequireFields(); + }); + + /* Implement a custom form without feeling refresh. */ + $('#formSettingForm .btn-primary').click(function() + { + var fields = ''; + $('#formSettingForm > .checkboxes > .checkbox-primary > input:checked').each(function() + { + fields += ',' + $(this).val(); + }); + + var link = createLink('custom', 'ajaxSaveCustomFields', 'module=bug§ion=custom&key=batchCreateFields'); + $.post(link, {'fields' : fields}, function() + { + showCheckedFields(fields); + $('#formSetting').parent().removeClass('open'); + + if($('#batchCreateForm table thead tr th.c-title').width() < 150) $titleCol.width(150); + + var fieldCount = $('#batchCreateForm .table thead>tr>th:visible').length; + $('.form-actions').attr('colspan', fieldCount); + + if(fieldCount > 10) + { + $('#batchCreateForm > .table-responsive').removeClass('scroll-none'); + $('#batchCreateForm > .table-responsive').css('overflow', 'auto'); + } + else + { + $('#batchCreateForm > .table-responsive').addClass('scroll-none'); + $('#batchCreateForm > .table-responsive').css('overflow', 'visible'); + } + }); + + return false; + }); }) +/** + * Show checked fields. + * + * @param string fields + * @access public + * @return void + */ +function showCheckedFields(fields) +{ + showFields = fields; + + var fieldList = ',' + fields + ','; + $('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function() + { + var field = ',' + $(this).val() + ','; + var $field = $('[name^=' + $(this).val() + ']'); + var required = ',' + requiredFields + ','; + var $fieldBox = $('.' + $(this).val() + 'Box' ); + if(fieldList.indexOf(field) >= 0 || required.indexOf(field) >= 0) + { + $fieldBox.removeClass('hidden'); + $field.removeAttr('disabled'); + } + else if(!$fieldBox.hasClass('hidden')) + { + $fieldBox.addClass('hidden'); + $field.attr('disabled', true); + } + }); +} + +/** + * Hidden require field. + * + * @access public + * @return void + */ +function hiddenRequireFields() +{ + $('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function() + { + var field = ',' + $(this).val() + ','; + var required = ',' + requiredFields + ','; + if(required.indexOf(field) >= 0) $(this).closest('div').addClass('hidden'); + }); +} + /** * Set opened builds. * @@ -149,3 +236,35 @@ $(document).keydown(function(event) inputFocusJump('down'); } }); + +/** + * Add item. + * + * @param object $obj + * @access public + * @return void + */ +function addItem(obj) +{ + var item = $('#addItem').html().replace(/%i%/g, itemIndex + 1); + $('' + item + '').insertAfter($(obj).closest('tr')); + + $(obj).closest('tr').next().find(".form-date").datepicker(); + $(obj).closest('tr').next().find('div[id$=_chosen]').remove(); + $(obj).closest('tr').next().find('.chosen').next('.picker').remove(); + $(obj).closest('tr').next().find('.chosen').chosen(); + + itemIndex ++; +} + +/** + * Delete item. + * + * @param object $obj + * @access public + * @return void + */ +function deleteItem(obj) +{ + $(obj).closest('tr').remove(); +} diff --git a/module/bug/lang/fr.php b/module/bug/lang/fr.php index 68341def99..e04e481637 100644 --- a/module/bug/lang/fr.php +++ b/module/bug/lang/fr.php @@ -425,7 +425,6 @@ $lang->bug->placeholder->newBuildName = 'Nom Nouv Build'; $lang->bug->featureBar['browse']['all'] = $lang->bug->allBugs; $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed; -$lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe; $lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe; $lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe; @@ -433,6 +432,7 @@ $lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved; $lang->bug->featureBar['browse']['more'] = $lang->more; $lang->bug->moreSelects['assignedbyme'] = $lang->bug->assignedByMe; +$lang->bug->moreSelects['openedbyme'] = $lang->bug->openedByMe; $lang->bug->moreSelects['unconfirmed'] = $lang->bug->unconfirmed; $lang->bug->moreSelects['assigntonull'] = $lang->bug->assignToNull; $lang->bug->moreSelects['longlifebugs'] = $lang->bug->longLifeBugs; diff --git a/module/bug/model.php b/module/bug/model.php index 236f66bef3..49eab4ed78 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -745,6 +745,8 @@ class bugModel extends model if($bug->execution and $bug->status != $oldBug->status) $this->loadModel('kanban')->updateLane($bug->execution, 'bug'); + if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $oldBug->feedback) $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status); + return common::createChanges($oldBug, $bug); } } @@ -845,6 +847,9 @@ class bugModel extends model unset($bug); } + $isBiz = $this->config->edition == 'biz'; + $isMax = $this->config->edition == 'max'; + /* Update bugs. */ foreach($bugs as $bugID => $bug) { @@ -866,6 +871,12 @@ class bugModel extends model $this->executeHooks($bugID); $allChanges[$bugID] = common::createChanges($oldBug, $bug); + + if(($isBiz || $isMax) && $oldBug->feedback && !isset($feedbacks[$oldBug->feedback])) + { + $feedbacks[$oldBug->feedback] = $oldBug->feedback; + $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status); + } } else { @@ -1138,6 +1149,8 @@ class bugModel extends model /* Link bug to build and release. */ $this->linkBugToBuild($bugID, $bug->resolvedBuild); + if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $oldBug->feedback) $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status); + return common::createChanges($oldBug, $bug); } @@ -1252,6 +1265,9 @@ class bugModel extends model $modules = array(); while($module = $stmt->fetch()) $modules[$module->id] = $module; + $isBiz = $this->config->edition == 'biz'; + $isMax = $this->config->edition == 'max'; + $changes = array(); foreach($bugIDList as $i => $bugID) { @@ -1297,6 +1313,12 @@ class bugModel extends model if($oldBug->execution) $this->loadModel('kanban')->updateLane($oldBug->execution, 'bug'); $changes[$bugID] = common::createChanges($oldBug, $bug); + + if(($isBiz || $isMax) && $oldBug->feedback && !isset($feedbacks[$oldBug->feedback])) + { + $feedbacks[$oldBug->feedback] = $oldBug->feedback; + $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status); + } } /* Link bug to build and release. */ @@ -1408,6 +1430,8 @@ class bugModel extends model if(isset($output['toColID'])) $this->kanban->moveCard($bugID, $output['fromColID'], $output['toColID'], $output['fromLaneID'], $output['toLaneID']); } + if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $oldBug->feedback) $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status); + return common::createChanges($oldBug, $bug); } @@ -3195,7 +3219,7 @@ class bugModel extends model echo zget($users, $bug->openedBy); break; case 'openedDate': - echo substr($bug->openedDate, 5, 11); + echo helper::isZeroDate($bug->openedDate) ? '' : substr($bug->openedDate, 5, 11); break; case 'openedBuild': $builds = array_flip($builds); @@ -3204,11 +3228,11 @@ class bugModel extends model $buildID = zget($builds, $build, ''); if($buildID == 'trunk') { - echo $build; + echo $build . ' '; } elseif($buildID and common::hasPriv('build', 'view')) { - echo html::a(helper::createLink('build', 'view', "buildID=$buildID"), $build, '', "title='$bug->openedBuild'"); + echo html::a(helper::createLink('build', 'view', "buildID=$buildID"), $build, '', "title='$bug->openedBuild'") . ' '; } } break; @@ -3216,10 +3240,10 @@ class bugModel extends model $this->printAssignedHtml($bug, $users); break; case 'assignedDate': - echo substr($bug->assignedDate, 5, 11); + echo helper::isZeroDate($bug->assignedDate) ? '' : substr($bug->assignedDate, 5, 11); break; case 'deadline': - echo $bug->deadline; + echo helper::isZeroDate($bug->deadline) ? '' : substr($bug->deadline, 5, 11); break; case 'resolvedBy': echo zget($users, $bug->resolvedBy, $bug->resolvedBy); @@ -3228,7 +3252,7 @@ class bugModel extends model echo zget($this->lang->bug->resolutionList, $bug->resolution); break; case 'resolvedDate': - echo substr($bug->resolvedDate, 5, 11); + echo helper::isZeroDate($bug->resolvedDate) ? '' : substr($bug->resolvedDate, 5, 11); break; case 'resolvedBuild': echo $bug->resolvedBuild; @@ -3237,13 +3261,13 @@ class bugModel extends model echo zget($users, $bug->closedBy); break; case 'closedDate': - echo substr($bug->closedDate, 5, 11); + echo helper::isZeroDate($bug->closedDate) ? '' : substr($bug->closedDate, 5, 11); break; case 'lastEditedBy': echo zget($users, $bug->lastEditedBy); break; case 'lastEditedDate': - echo substr($bug->lastEditedDate, 5, 11); + echo helper::isZeroDate($bug->lastEditedDate) ? '' : substr($bug->lastEditedDate, 5, 11); break; case 'actions': echo $this->buildOperateMenu($bug, 'browse'); diff --git a/module/bug/view/batchcreate.html.php b/module/bug/view/batchcreate.html.php index 91c02ab591..df075784d6 100755 --- a/module/bug/view/batchcreate.html.php +++ b/module/bug/view/batchcreate.html.php @@ -14,6 +14,24 @@ include '../../common/view/header.html.php'; js::set('requiredFields', $config->bug->create->requiredFields); ?> +bug->create->requiredFields) as $field) +{ + if($field) + { + $requiredFields[$field] = ''; + if(strpos(",{$config->bug->list->customBatchCreateFields},", ",{$field},") !== false) $visibleFields[$field] = ''; + } +} +?> +

@@ -30,49 +48,32 @@ js::set('requiredFields', $config->bug->create->requiredFields);

- - bug->create->requiredFields) as $field) - { - if($field) - { - $requiredFields[$field] = ''; - if(strpos(",{$config->bug->list->customBatchCreateFields},", ",{$field},") !== false) $visibleFields[$field] = ''; - } - } - ?>
- + systemMode == 'new'):?> - + - + - - - - - - - - + + + + + + + + bug->getFlowExtendFields(); foreach($extendFields as $extendField) @@ -81,6 +82,7 @@ js::set('requiredFields', $config->bug->create->requiredFields); echo ""; } ?> + @@ -106,13 +108,13 @@ js::set('requiredFields', $config->bug->create->requiredFields); $browser = $i == 1 ? '' : 'ditto'; ?> - - + + systemMode == 'new'):?> - + - + - - - - - - - - + + + + + + + + loadModel('flow'); foreach($extendFields as $extendField) echo "control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[$i]") . ""; ?> + @@ -161,12 +169,12 @@ js::set('requiredFields', $config->bug->create->requiredFields); ?> - + systemMode == 'new'):?> - + - + - - - - - - - - + + + + + + + + loadModel('flow'); foreach($extendFields as $extendField) echo "control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[$i]") . ""; ?> + - @@ -213,16 +227,17 @@ js::set('requiredFields', $config->bug->create->requiredFields); +
idAB;?>'> product->branch;?> branchBox'> product->branch;?> '> bug->module;?> '>model) and $project->model == 'kanban') ? $lang->bug->kanban : $lang->bug->project;?> projectBox'>model) and $project->model == 'kanban') ? $lang->bug->kanban : $lang->bug->project;?> '>model) and $project->model == 'kanban') ? $lang->bug->kanban : $lang->bug->execution;?> executionBox'>model) and $project->model == 'kanban') ? $lang->bug->kanban : $lang->bug->execution;?> bug->openedBuild;?> bug->title;?> kanbancard->region;?> kanbancard->lane;?> '>bug->deadline;?>'>bug->steps;?>'>typeAB;?>'>bug->pri;?>'>bug->severity;?>'>bug->os;?>'>bug->browser;?>'>bug->keywords;?> deadlineBox'>bug->deadline;?> stepsBox'>bug->steps;?> typeBox'>typeAB;?> priBox'>bug->pri;?> severityBox'>bug->severity;?> osBox'>bug->os;?> browserBox'>bug->browser;?> keywordsBox'>bug->keywords;?> {$extendField->name}actions;?>
' style='overflow:visible'> branchBox' style='overflow:visible'> ' style='overflow:visible'> projectBox' style='overflow:visible'> ' style='overflow:visible'> executionBox' style='overflow:visible'>
@@ -132,18 +134,24 @@ js::set('requiredFields', $config->bug->create->requiredFields);
'>'>' style='overflow:visible'> bug->typeList, $type, "class='form-control chosen'");?>' style='overflow:visible'> bug->priList, $pri, "class='form-control'");?>' style='overflow:visible'>bug->severityList, '3', "class='form-control'");?>' style='overflow:visible'> bug->osList, $os, "class='form-control chosen'");?>' style='overflow:visible'> bug->browserList, $browser, "class='form-control chosen'");?>'> deadlineBox'> stepsBox'> typeBox' style='overflow:visible'> bug->typeList, $type, "class='form-control chosen'");?> priBox' style='overflow:visible'> bug->priList, $pri, "class='form-control'");?> severityBox' style='overflow:visible'>bug->severityList, '3', "class='form-control'");?> osBox' style='overflow:visible'> bug->osList, $os, "class='form-control chosen'");?> browserBox' style='overflow:visible'> bug->browserList, $browser, "class='form-control chosen'");?> keywordsBox'> + + + + +
' style='overflow:visible'> branchBox' style='overflow:visible'> ' style='overflow:visible'> projectBox' style='overflow:visible'> ' style='overflow:visible'> executionBox' style='overflow:visible'>
@@ -186,24 +194,30 @@ js::set('requiredFields', $config->bug->create->requiredFields);
'>'>' style='overflow:visible'> bug->typeList, $type, "class='form-control chosen'");?>' style='overflow:visible'> bug->priList, $pri, "class='form-control'");?>' style='overflow:visible'>bug->severityList, '3', "class='form-control'");?>' style='overflow:visible'> bug->osList, $os, "class='form-control chosen'");?>' style='overflow:visible'> bug->browserList, $browser, "class='form-control chosen'");?>'> deadlineBox'> stepsBox'> typeBox' style='overflow:visible'> bug->typeList, $type, "class='form-control chosen'");?> priBox' style='overflow:visible'> bug->priList, $pri, "class='form-control'");?> severityBox' style='overflow:visible'>bug->severityList, '3', "class='form-control'");?> osBox' style='overflow:visible'> bug->osList, $os, "class='form-control chosen'");?> browserBox' style='overflow:visible'> bug->browserList, $browser, "class='form-control chosen'");?> keywordsBox'> + + + + +
+
- - + + systemMode == 'new'):?> - + - + - - - - - - - - + + + + + + + + loadModel('flow'); foreach($extendFields as $extendField) echo "control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[%s]") . ""; ?> +
%s' style='overflow:visible'> productBox' style='overflow:visible'> ' style='overflow:visible'> projectBox' style='overflow:visible'> ' style='overflow:visible'> executionBox' style='overflow:visible'>
@@ -238,21 +253,74 @@ js::set('requiredFields', $config->bug->create->requiredFields);
'>'>' style='overflow:visible'> bug->typeList, $type, "class='form-control chosen'");?>' style='overflow:visible'> bug->priList, '', "class='form-control'");?>' style='overflow:visible'>bug->severityList, '3', "class='form-control'");?>' style='overflow:visible'> bug->osList, $os, "class='form-control chosen'");?>' style='overflow:visible'> bug->browserList, $browser, "class='form-control chosen'");?>'> deadlineBox'> stepsBox'> typeBox' style='overflow:visible'> bug->typeList, $type, "class='form-control chosen'");?> priBox' style='overflow:visible'> bug->priList, $pri, "class='form-control'");?> severityBox' style='overflow:visible'>bug->severityList, '3', "class='form-control'");?> osBox' style='overflow:visible'> bug->osList, $os, "class='form-control chosen'");?> browserBox' style='overflow:visible'> bug->browserList, $browser, "class='form-control chosen'");?> keywordsBox'> + + +
+
+ + + + + + + systemMode == 'new'):?> + + + + + + + + + + + + + + + + + + loadModel('flow'); + foreach($extendFields as $extendField) echo "control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[$i]") . ""; + ?> + + + +
diff --git a/module/custom/control.php b/module/custom/control.php index e057255657..a642380ace 100644 --- a/module/custom/control.php +++ b/module/custom/control.php @@ -676,14 +676,17 @@ class custom extends control $account = $this->app->user->account; if($this->server->request_method == 'POST') { - $fields = $this->post->fields; + $fields = $this->post->fields; if(is_array($fields)) $fields = join(',', $fields); $this->loadModel('setting')->setItem("$account.$module.$section.$key", $fields); + if(in_array($module, array('task', 'testcase', 'story')) and $section == 'custom' and in_array($key, array('createFields', 'batchCreateFields'))) return; + if($module == 'bug' and $section == 'custom' and $key == 'batchCreateFields') return; } else { $this->loadModel('setting')->deleteItems("owner=$account&module=$module§ion=$section&key=$key"); } + return print(js::reload('parent')); } diff --git a/module/custom/model.php b/module/custom/model.php index 2ff04d5438..93274c6418 100644 --- a/module/custom/model.php +++ b/module/custom/model.php @@ -701,8 +701,10 @@ class customModel extends model } } + $vision = $this->config->vision; + $this->loadModel('setting'); - $this->setting->setItems("system.{$moduleName}", $requiredFields); + $this->setting->setItems("system.{$moduleName}@$vision", $requiredFields); } /** diff --git a/module/custom/view/set.html.php b/module/custom/view/set.html.php index 5e784588de..d3eb53ad46 100644 --- a/module/custom/view/set.html.php +++ b/module/custom/view/set.html.php @@ -234,6 +234,7 @@ EOT; + @@ -270,6 +271,7 @@ EOT;
custom->notice->canNotAdd;?>
+ diff --git a/module/datatable/control.php b/module/datatable/control.php index f365b7e8b1..1f2ba3a0c1 100644 --- a/module/datatable/control.php +++ b/module/datatable/control.php @@ -67,6 +67,8 @@ class datatable extends control $this->app->loadConfig('testtask'); $this->config->testcase->datatable->defaultField = $this->config->testtask->datatable->defaultField; $this->config->testcase->datatable->fieldList['actions']['width'] = '100'; + $this->config->testcase->datatable->fieldList['status']['title'] = $this->lang->testcase->executionStatus; + $this->config->testcase->datatable->fieldList['status']['width'] = '90'; } if($module == 'testcase') { diff --git a/module/design/css/linkcommit.css b/module/design/css/linkcommit.css index d1a2a856a5..006029f60f 100644 --- a/module/design/css/linkcommit.css +++ b/module/design/css/linkcommit.css @@ -3,6 +3,7 @@ .searchBox .srearch-date{float: left; width: 20%} .searchBox h4{float:left;display: inline-block} .searchBox span{float:left;line-height:30px} +.body-modal .main-header {z-index: 5;} #logForm .table thead th{background: #efefef} #begin{margin-right:5px} #end{margin-left:5px} diff --git a/module/doc/config.php b/module/doc/config.php index 626efc5a30..45fac598de 100644 --- a/module/doc/config.php +++ b/module/doc/config.php @@ -21,9 +21,10 @@ $config->doc->custom->objectLibs = $config->doc->customObjectLibs; $config->doc->custom->showLibs = 'zero,children'; $config->doc->editor = new stdclass(); -$config->doc->editor->create = array('id' => 'content', 'tools' => 'fullTools'); -$config->doc->editor->edit = array('id' => 'content', 'tools' => 'fullTools'); -$config->doc->editor->view = array('id' => 'comment,lastComment', 'tools' => 'simple'); +$config->doc->editor->create = array('id' => 'content', 'tools' => 'fullTools'); +$config->doc->editor->edit = array('id' => 'content', 'tools' => 'fullTools'); +$config->doc->editor->view = array('id' => 'comment,lastComment', 'tools' => 'simple'); +$config->doc->editor->objectlibs = array('id' => 'comment,lastComment', 'tools' => 'simple'); $config->doc->markdown = new stdclass(); $config->doc->markdown->create = array('id' => 'contentMarkdown', 'tools' => 'withchange'); diff --git a/module/doc/control.php b/module/doc/control.php index d66c7ae8f4..52a5c4c5f1 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -483,6 +483,7 @@ class doc extends control $this->view->moduleOptionMenu = $this->tree->getOptionMenu($libID, 'doc', $startModuleID = 0); $this->view->type = $type; $this->view->libs = $this->doc->getLibs('all', $extra = 'withObject|noBook', $libID, $objectID); + $this->view->lib = $lib; $this->view->groups = $this->loadModel('group')->getPairs(); $this->view->users = $this->user->getPairs('noletter|noclosed|nodeleted', $doc->users); $this->display(); diff --git a/module/doc/js/common.js b/module/doc/js/common.js index 432a790f3e..be9b87367f 100644 --- a/module/doc/js/common.js +++ b/module/doc/js/common.js @@ -50,7 +50,7 @@ function toggleAcl(acl, type) var notice = typeof(noticeAcl[libType][acl]) != 'undefined' ? noticeAcl[libType][acl] : ''; $('#noticeAcl').html(notice); - if((libType == 'custom' || libType == 'api') && acl == 'private') $('#whiteListBox').addClass('hidden'); + if((libType == 'custom' || libType == 'api' || libType == 'book') && acl == 'private') $('#whiteListBox').addClass('hidden'); if(libType == 'project' && typeof(doclibID) != 'undefined') { diff --git a/module/doc/js/edit.js b/module/doc/js/edit.js index 3e71c6be4c..c5c0f24b49 100644 --- a/module/doc/js/edit.js +++ b/module/doc/js/edit.js @@ -169,7 +169,7 @@ function loadWhitelist(libID) $('#aclcustom').parent('.radio-inline').removeClass('hidden'); $('#users').replaceWith(users); - $('#user').next('.picker').remove(); + $('#users').next('.picker').remove(); $('#users').picker(); } }); diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index d63e726e2d..90e77680b5 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -48,7 +48,7 @@ $lang->doc->common = 'Dok'; $lang->doc->id = 'ID'; $lang->doc->product = $lang->productCommon; $lang->doc->project = 'Project'; -$lang->doc->execution = $lang->executionCommon; +$lang->doc->execution = $lang->execution->common; $lang->doc->lib = 'Bibliothek'; $lang->doc->module = 'Modul'; $lang->doc->object = 'Object'; @@ -161,7 +161,7 @@ $lang->doc->allProjects = 'All' . $lang->projectCommon . 's'; $lang->doc->libTypeList['product'] = $lang->productCommon . ' Bibliothek'; if($config->systemMode == 'new') $lang->doc->libTypeList['project'] = 'Project Library'; -$lang->doc->libTypeList['execution'] = $lang->executionCommon . ' Bibliothek'; +$lang->doc->libTypeList['execution'] = $lang->execution->common . ' Bibliothek'; $lang->doc->libTypeList['api'] = 'API Library'; $lang->doc->libTypeList['custom'] = 'Eigene Bibliothek'; @@ -251,8 +251,8 @@ $lang->doc->noticeAcl['lib']['project']['default'] = 'Users who can access the $lang->doc->noticeAcl['lib']['project']['open'] = 'Users who can access the selected project can access it.'; $lang->doc->noticeAcl['lib']['project']['private'] = 'Users who can access the selected project or users in the whiltelist can access it.'; $lang->doc->noticeAcl['lib']['project']['custom'] = 'Users who can access the selected project or users in the whiltelist can access it.'; -$lang->doc->noticeAcl['lib']['execution']['default'] = "Users who can access the selected {$lang->executionCommon} can access it."; -$lang->doc->noticeAcl['lib']['execution']['custom'] = "Users who can access the selected {$lang->executionCommon} or users in the whiltelist can access it."; +$lang->doc->noticeAcl['lib']['execution']['default'] = "Users who can access the selected {$lang->execution->common} can access it."; +$lang->doc->noticeAcl['lib']['execution']['custom'] = "Users who can access the selected {$lang->execution->common} or users in the whiltelist can access it."; $lang->doc->noticeAcl['lib']['api']['open'] = 'All users can access it.'; $lang->doc->noticeAcl['lib']['api']['custom'] = 'Users in the whitelist can access it.'; $lang->doc->noticeAcl['lib']['api']['private'] = 'Only the one who created it can access it.'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index d3e052be03..22ffeedc54 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -251,8 +251,8 @@ $lang->doc->noticeAcl['lib']['project']['default'] = 'Users who can access the $lang->doc->noticeAcl['lib']['project']['open'] = 'Users who can access the selected project can access it.'; $lang->doc->noticeAcl['lib']['project']['private'] = 'Users who can access the selected project or users in the whiltelist can access it.'; $lang->doc->noticeAcl['lib']['project']['custom'] = 'Users in the whiltelist can access it.'; -$lang->doc->noticeAcl['lib']['execution']['default'] = "Users who can access the selected {$lang->executionCommon} can access it."; -$lang->doc->noticeAcl['lib']['execution']['custom'] = "Users who can access the selected {$lang->executionCommon} or users in the whiltelist can access it."; +$lang->doc->noticeAcl['lib']['execution']['default'] = "Users who can access the selected {$lang->execution->common} can access it."; +$lang->doc->noticeAcl['lib']['execution']['custom'] = "Users who can access the selected {$lang->execution->common} or users in the whiltelist can access it."; $lang->doc->noticeAcl['lib']['api']['open'] = 'All users can access it.'; $lang->doc->noticeAcl['lib']['api']['custom'] = 'Users in the whitelist can access it.'; $lang->doc->noticeAcl['lib']['api']['private'] = 'Only the one who created it can access it.'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index b9379ba42a..e7f59b7b84 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -48,7 +48,7 @@ $lang->doc->common = 'Gestion Documentaire'; $lang->doc->id = 'ID'; $lang->doc->product = $lang->productCommon; $lang->doc->project = 'Project'; -$lang->doc->execution = $lang->executionCommon; +$lang->doc->execution = $lang->execution->common; $lang->doc->lib = 'Bibliothèque'; $lang->doc->module = 'Catégorie'; $lang->doc->object = 'Object'; @@ -161,7 +161,7 @@ $lang->doc->allProjects = 'All' . $lang->projectCommon . 's'; $lang->doc->libTypeList['product'] = $lang->productCommon . ' Library'; if($config->systemMode == 'new') $lang->doc->libTypeList['project'] = 'Project Library'; -$lang->doc->libTypeList['execution'] = 'Bibliothèque ' . $lang->executionCommon; +$lang->doc->libTypeList['execution'] = 'Bibliothèque ' . $lang->execution->common; $lang->doc->libTypeList['api'] = 'API Library'; $lang->doc->libTypeList['custom'] = 'Bib. Personnalisée'; @@ -251,8 +251,8 @@ $lang->doc->noticeAcl['lib']['project']['default'] = 'Les utilisateurs qui ont $lang->doc->noticeAcl['lib']['project']['open'] = 'Users who can access the selected project can access it.'; $lang->doc->noticeAcl['lib']['project']['private'] = 'Users who can access the selected project or users in the whiltelist can access it.'; $lang->doc->noticeAcl['lib']['project']['custom'] = 'Les utilisateurs qui ont accès au Projet ou les utilisateurs de la Liste Blanche peuvent y accéder.'; -$lang->doc->noticeAcl['lib']['execution']['default'] = "Les utilisateurs qui ont accès au {$lang->executionCommon} peuvent y accéder."; -$lang->doc->noticeAcl['lib']['execution']['custom'] = "Les utilisateurs qui ont accès au {$lang->executionCommon} ou les utilisateurs de la Liste Blanche peuvent y accéder."; +$lang->doc->noticeAcl['lib']['execution']['default'] = "Les utilisateurs qui ont accès au {$lang->execution->common} peuvent y accéder."; +$lang->doc->noticeAcl['lib']['execution']['custom'] = "Les utilisateurs qui ont accès au {$lang->execution->common} ou les utilisateurs de la Liste Blanche peuvent y accéder."; $lang->doc->noticeAcl['lib']['api']['open'] = 'All users can access it.'; $lang->doc->noticeAcl['lib']['api']['custom'] = 'Users in the whitelist can access it.'; $lang->doc->noticeAcl['lib']['api']['private'] = 'Only the one who created it can access it.'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index ddbd9cea78..c42abbd0c2 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -251,8 +251,8 @@ $lang->doc->noticeAcl['lib']['project']['default'] = "有所选项目访问权 $lang->doc->noticeAcl['lib']['project']['open'] = "有所选项目访问权限的用户可以访问。"; $lang->doc->noticeAcl['lib']['project']['private'] = "有所选项目访问权限或白名单里的用户可以访问。"; $lang->doc->noticeAcl['lib']['project']['custom'] = "白名单的用户可以访问。"; -$lang->doc->noticeAcl['lib']['execution']['default'] = "有所选{$lang->executionCommon}访问权限的用户可以访问。"; -$lang->doc->noticeAcl['lib']['execution']['custom'] = "有所选{$lang->executionCommon}访问权限或白名单里的用户可以访问。"; +$lang->doc->noticeAcl['lib']['execution']['default'] = "有所选{$lang->execution->common}访问权限的用户可以访问。"; +$lang->doc->noticeAcl['lib']['execution']['custom'] = "有所选{$lang->execution->common}访问权限或白名单里的用户可以访问。"; $lang->doc->noticeAcl['lib']['api']['open'] = '所有人都可以访问。'; $lang->doc->noticeAcl['lib']['api']['custom'] = '白名单的用户可以访问。'; $lang->doc->noticeAcl['lib']['api']['private'] = '只有创建者自己可以访问。'; diff --git a/module/doc/view/edit.html.php b/module/doc/view/edit.html.php index 9a092fe015..3569041e5c 100644 --- a/module/doc/view/edit.html.php +++ b/module/doc/view/edit.html.php @@ -83,8 +83,9 @@ diff --git a/module/doc/view/objectlibs.html.php b/module/doc/view/objectlibs.html.php index cd6df9b47c..26478698e9 100644 --- a/module/doc/view/objectlibs.html.php +++ b/module/doc/view/objectlibs.html.php @@ -11,6 +11,7 @@ */ ?> +tab == 'execution'):;?> diff --git a/module/execution/control.php b/module/execution/control.php index 8f334c11d6..1cc1c84b54 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -412,13 +412,26 @@ class execution extends control } elseif($groupBy == 'assignedTo' and $filter == 'undone') { + $multiTaskCount = array(); foreach($groupTasks as $assignedTo => $tasks) { foreach($tasks as $i => $task) { if($task->status != 'wait' and $task->status != 'doing') { - $allCount -= 1; + if($task->mode == 'multi') + { + if(!isset($multiTaskCount[$task->id])) + { + $multiTaskCount[$task->id] = true; + $allCount -= 1; + } + } + else + { + $allCount -= 1; + } + unset($groupTasks[$assignedTo][$i]); } } @@ -805,6 +818,14 @@ class execution extends control } $actionURL = $this->createLink('execution', 'story', "executionID=$executionID&orderBy=$orderBy&type=bySearch&queryID=myQueryID"); $branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products)); + $branchOption = array(); + foreach($branchGroups as $productID => $branches) + { + foreach($branches as $branchID => $name) + { + $branchOption[$branchID] = $name; + } + } $this->execution->buildStorySearchForm($products, $branchGroups, $modules, $queryID, $actionURL, 'executionStory', $executionID); /* Header and position. */ @@ -867,9 +888,10 @@ class execution extends control $this->view->pager = $pager; $this->view->setModule = true; $this->view->branchGroups = $branchGroups; + $this->view->branchOption = $branchOption; $this->view->canBeChanged = common::canModify('execution', $execution); // Determines whether an object is editable. $this->view->showBranch = $showBranch; - $this->view->storyStages = $this->product->batchGetStoryStage($stories); + $this->view->storyStages = $this->product->batchGetStoryStage($stories); $this->display(); } @@ -984,6 +1006,9 @@ class execution extends control $showModule = !empty($this->config->datatable->bugBrowse->showModule) ? $this->config->datatable->bugBrowse->showModule : ''; + /* Process the openedBuild and resolvedBuild fields. */ + $bugs = $this->bug->processBuildForBugs($bugs); + /* Assign. */ $this->view->title = $title; $this->view->position = $position; @@ -1280,6 +1305,49 @@ class execution extends control $this->display(); } + /** + * Kanban CFD. + * + * @param int $executionID + * @param string $type + * @access public + * @return void + */ + public function cfd($executionID = 0, $type = 'story') + { + $execution = $this->commonAction($executionID); + $executionID = $execution->id; + + $this->loadModel('kanban'); + $this->app->loadClass('date'); + + list($begin, $end) = $this->execution->getBeginEnd4CFD($execution); + $dateList = date::getDateList($begin, $end, 'Y-m-d', ''); + + $this->view->title = $this->lang->execution->CFD; + $this->view->type = $type; + $this->view->execution = $execution; + $this->view->executionName = $execution->name; + $this->view->executionID = $executionID; + $this->view->chartData = $this->execution->buildCFDData($executionID, $dateList, $type); + $this->display(); + } + + /** + * Compute cfd datas. + * + * @param string $reload + * @param int $executionID + * @access public + * @return void + */ + public function computeCFD($reload = 'no', $executionID = 0, $date = '') + { + $date = date('Y-m-d', strtotime($date)); + $this->execution->computeCFD($executionID, $date); + if($reload == 'yes') return print(js::reload('parent')); + } + /** * Fix burn for first date. * @@ -1522,7 +1590,9 @@ class execution extends control if(!empty($this->config->user->moreLink)) $this->config->moreLinks["RD"] = $this->config->user->moreLink; $this->loadModel('product'); - $allProducts = $this->config->systemMode == 'classic' ? $this->product->getPairs('noclosed') : $this->product->getProductPairsByProject($projectID, 'noclosed'); + $allProducts = $this->config->systemMode == 'classic' ? $this->product->getPairs('noclosed') : $this->product->getProductPairsByProject($projectID, 'noclosed'); + $copyProjects = $this->loadModel('project')->getPairsByProgram(isset($project->parent) ? $project->parent : '', 'noclosed', '', 'order_asc', '', isset($project->model) ? $project->model : ''); + $copyProjectID = ($projectID == 0) ? key($copyProjects) : $projectID; $this->view->title = (($this->app->tab == 'execution') and ($this->config->systemMode == 'new')) ? $this->lang->execution->createExec : $this->lang->execution->create; $this->view->position[] = $this->view->title; @@ -1537,6 +1607,8 @@ class execution extends control $this->view->team = $team; $this->view->teams = array(0 => '') + $this->execution->getCanCopyObjects((int)$projectID); $this->view->allProjects = array(0 => '') + $this->project->getPairsByModel('all', 0, 'noclosed'); + $this->view->copyProjects = $copyProjects; + $this->view->copyExecutions = array('' => '') + $this->execution->getList($copyProjectID); $this->view->executionID = $executionID; $this->view->productID = $productID; $this->view->projectID = $projectID; @@ -3970,4 +4042,18 @@ class execution extends control echo json_encode($date); } } + + /** + * Ajax get copy project executions. + * + * @param int $projectID + * @access public + * @return void + */ + public function ajaxGetCopyProjectExecutions($projectID = 0) + { + $executions = $this->execution->getList($projectID); + echo json_encode($executions); + } + } diff --git a/module/execution/css/cfd.css b/module/execution/css/cfd.css new file mode 100644 index 0000000000..fd514e009f --- /dev/null +++ b/module/execution/css/cfd.css @@ -0,0 +1,6 @@ +.main-content > h2 {font-size: 16px;} +#cfdWrapper {max-width: 1400px; margin: 0 auto; padding: 25px 100px 10px; position: relative;} +#cfdYUnit {position: absolute; color: #CBD0DB; top: 27px; left: 130px;} +#cfdXUnit {position: absolute; color: #CBD0DB; bottom: 35px; right: 60px;} + +.pull-left .input-control {margin-right: 10px;} diff --git a/module/execution/css/create.css b/module/execution/css/create.css index cb9f540c66..6a7e4ef15c 100644 --- a/module/execution/css/create.css +++ b/module/execution/css/create.css @@ -30,3 +30,6 @@ #dateRange {vertical-align: top; padding-top: 13px;} #dateRangeOption {vertical-align: top; padding-top: 13px;} +#copyProjectModal .projectSelect {display: inline-block; margin-left: 10px; width: 20%;} +#copyProjectModal .titleBox{position: relative; bottom: 3px; display: inline-block;} +a.chosen-single > div > b {top: -4px !important;} diff --git a/module/execution/css/task.css b/module/execution/css/task.css index 7b58f130fe..df5a1d9368 100644 --- a/module/execution/css/task.css +++ b/module/execution/css/task.css @@ -10,3 +10,4 @@ th.c-deadline {text-align: center;} .btn-toolbar > .btn {margin-right: 5px !important;} #taskList .c-progress{padding-right: 8px; text-align: right;} #datatable-taskList .c-progress{padding-right: 8px; text-align: right;} +.c-finishedBy, .c-lastEditedBy {overflow: hidden; text-overflow: ellipsis; white-space: nowrap;} diff --git a/extension/lite/workflowdatasource/ext/view/browse.flow.html.hook.php b/module/execution/js/cfd.js similarity index 100% rename from extension/lite/workflowdatasource/ext/view/browse.flow.html.hook.php rename to module/execution/js/cfd.js diff --git a/module/execution/js/create.js b/module/execution/js/create.js index 2cb6a485bb..6dcd9c0483 100644 --- a/module/execution/js/create.js +++ b/module/execution/js/create.js @@ -8,7 +8,11 @@ $(function() var heightType = $("[name='heightType']:checked").val(); setCardCount(heightType); - $('#copyProjects a').click(function(){setCopyProject($(this).data('id')); $('#copyProjectModal').modal('hide')}); + $(document).on('click', '#copyProjects a', function() + { + setCopyProject($(this).data('id')); $('#copyProjectModal').modal('hide'); + }); + $('#begin').on('change', function() { $("#end").val(''); @@ -168,3 +172,43 @@ function subString(title, stringLength) return title; } + +/** + * Load project executions. + * + * @param int $projectID + * @access public + * @return void + */ +function loadProjectExecutions(projectID) +{ + $.get(createLink('execution', 'ajaxGetCopyProjectExecutions', 'projectID=' + projectID + '&$copyExecutionID' + copyExecutionID), function(data) + { + if(data != '[]') + { + $('.alert').replaceWith("
"); + $("#copyProjects > div[data-id != '']").remove(); + $(".model-body").remove(); + var data = JSON.parse(data); + if(copyExecutionID != 0 ) + { + $('#copyProjects').append(""); + } + $.each(data, function(id, execution) + { + var type = execution.type == 'stage' ? 'waterfall' : execution.type; + var active = copyExecutionID == id ? ' active' : ''; + $('#copyProjects').append(""); + }); + } + else if(data == '[]' && copyExecutionID == 0) + { + $('#copyProjects').replaceWith("
" + copyNoExecution + "
"); + } + else if(data == '[]' && copyExecutionID != 0) + { + $("#copyProjects > div[data-id != '']").remove(); + $('#copyProjects').append(""); + } + }); +} diff --git a/module/execution/js/kanban.js b/module/execution/js/kanban.js index bfe4282281..079b48cd71 100644 --- a/module/execution/js/kanban.js +++ b/module/execution/js/kanban.js @@ -235,10 +235,12 @@ function createLaneMenu(options) var privs = lane.actions; if(!privs.length) return []; - var items = []; + var items = []; + var regionID = lane.$kanbanData.region; + var kanbanID = lane.$kanbanData.kanban; if(privs.includes('editLaneName')) items.push({label: kanbanLang.editLaneName, icon: 'edit', url: createLink('kanban', 'editLaneName', 'laneID=' + lane.id + '&executionID=0&from=kanban'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '635px'}}); if(privs.includes('editLaneColor')) items.push({label: kanbanLang.editLaneColor, icon: 'color', url: createLink('kanban', 'editLaneColor', 'laneID=' + lane.id + '&executionID=0&from=kanban'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '635px'}}); - if(privs.includes('deleteLane')) items.push({label: kanbanLang.deleteLane, icon: 'trash', url: createLink('kanban', 'deleteLane', 'lane=' + lane.id), attrs: {'target': 'hiddenwin'}}); + if(privs.includes('deleteLane')) items.push({label: kanbanLang.deleteLane, icon: 'trash', url: createLink('kanban', 'deleteLane', 'regionID=' + regionID + '&kanbanID=' + kanbanID + '&lane=' + lane.id), attrs: {'target': 'hiddenwin'}}); var bounds = options.$trigger[0].getBoundingClientRect(); items.$options = {x: bounds.right, y: bounds.top}; @@ -297,6 +299,59 @@ function createColumnCreateMenu(options) return items; } +/** + * Update region name. + * + * @param int $regionID + * @param string $name + * @access public + * @return void + */ +function updateRegionName(regionID, name) +{ + $('.region[data-id="' + regionID + '"] > .region-header > strong:first').text(name); +} + +/** + * Update lane name. + * + * @param int $laneID + * @param string $name + * @access public + * @return void + */ +function updateLaneName(laneID, name) +{ + $('.kanban-lane[data-id="' + laneID + '"] > .kanban-lane-name > span').text(name); +} + +/** + * Update lane color. + * + * @param int $laneID + * @param string $color + * @access public + * @return void + */ +function updateLaneColor(laneID, color) +{ + $('.kanban-lane[data-id="' + laneID + '"] > .kanban-lane-name').css('background-color', color); +} + +/** + * Update column name. + * + * @param int $columnID + * @param string $name + * @param string $color + * @access public + * @return void + */ +function updateColumnName(columnID, name, color) +{ + $('.kanban-col[data-id="' + columnID + '"] > div.title > span:first').text(name).css('color', color); +} + /** * Hide kanban action */ @@ -835,7 +890,7 @@ function updateRegion(regionID, regionData = []) if(!regionData) regionData = regions[regionID]; var data = groupBy == 'default' ? regionData.groups : regionData; - if(data == null || data.length == 0) + if((data == null || data.length == 0) && rdSearchValue != '') { if(groupBy == 'default') $("div[data-id^=" + regionID + "].region").hide(); if(groupBy != 'default') $("div[data-id^=" + regionID + "].kanban").hide(); @@ -1274,7 +1329,7 @@ function handleSortCards(event) orders.splice(orders.indexOf(fromID), 1); orders.splice(orders.indexOf(toID) + (event.insert === 'before' ? 0 : 1), 0, fromID); - var url = createLink('kanban', 'sortCard', 'kanbanID=' + executionID + '&laneID=' + newLaneID + '&columnID=' + newColID + '&cards=' + orders.join(',') + '&cardID=' + toID); + var url = createLink('kanban', 'sortCard', 'kanbanID=' + executionID + '&laneID=' + newLaneID + '&columnID=' + newColID + '&cards=' + orders.join(',')); $.getJSON(url, function(response) { if(response.result === 'fail') @@ -1608,6 +1663,7 @@ $(function() { $.get(createLink('execution', 'ajaxUpdateKanban', "executionID=" + executionID + "&entertime=" + entertime + "&browseType=" + browseType + "&groupBy=" + groupBy + '&from=RD&searchValue=' + rdSearchValue), function(data) { + if(lastUpdateData == '') lastUpdateData = data; if(data && lastUpdateData !== data) { lastUpdateData = data; diff --git a/module/execution/js/taskkanban.js b/module/execution/js/taskkanban.js index c7c48cf4ff..4b402c6b02 100644 --- a/module/execution/js/taskkanban.js +++ b/module/execution/js/taskkanban.js @@ -1,3 +1,17 @@ +/** + * Update column name. + * + * @param int $columnID + * @param string $name + * @param string $color + * @access public + * @return void + */ +function updateColumnName(columnID, name, color) +{ + $('.kanban-col[data-id="' + columnID + '"] > div.title > span:first').text(name).css('color', color); +} + /** * Change view. * @@ -1109,7 +1123,7 @@ function handleSortCards(event) orders.splice(orders.indexOf(fromID), 1); orders.splice(orders.indexOf(toID) + (event.insert === 'before' ? 0 : 1), 0, fromID); - var url = createLink('kanban', 'sortCard', 'kanbanID=' + executionID + '&laneID=' + newLaneID + '&columnID=' + newColID + '&cards=' + orders.join(',') + '&cardID=' + toID); + var url = createLink('kanban', 'sortCard', 'kanbanID=' + executionID + '&laneID=' + newLaneID + '&columnID=' + newColID + '&cards=' + orders.join(',')); $.getJSON(url, function(response) { if(response.result === 'fail') @@ -1268,6 +1282,7 @@ $(function() { $.get(createLink('execution', 'ajaxUpdateKanban', "executionID=" + executionID + "&entertime=" + entertime + "&browseType=" + browseType + "&groupBy=" + groupBy + '&from=execution&searchValue=' + searchValue), function(data) { + if(lastUpdateData == '') lastUpdateData = data; if(data && lastUpdateData !== data) { lastUpdateData = data; diff --git a/module/execution/lang/de.php b/module/execution/lang/de.php index c39f1544ad..41d14ce627 100644 --- a/module/execution/lang/de.php +++ b/module/execution/lang/de.php @@ -118,6 +118,7 @@ $lang->execution->relatedMember = 'Teammitglieder'; $lang->execution->watermark = 'Exported by ZenTao'; $lang->execution->burnXUnit = '(Date)'; $lang->execution->burnYUnit = '(Hours)'; +$lang->execution->count = '(Count)'; $lang->execution->waitTasks = 'Waiting Tasks'; $lang->execution->viewByUser = 'By User'; $lang->execution->oneProduct = "Only one stage can be linked {$lang->productCommon}"; @@ -165,6 +166,10 @@ $lang->execution->lifeTimeList['short'] = "Short-Term"; $lang->execution->lifeTimeList['long'] = "Long-Term"; $lang->execution->lifeTimeList['ops'] = "DevOps"; +$lang->execution->cfdTypeList['story'] = "{$lang->SRCommon}"; +$lang->execution->cfdTypeList['task'] = "Task"; +$lang->execution->cfdTypeList['bug'] = "Bug"; + $lang->team = new stdclass(); $lang->team->account = 'Konto'; $lang->team->role = 'Rolle'; @@ -221,6 +226,8 @@ $lang->execution->build = 'Builds'; $lang->execution->testtask = 'Testaufgaben'; $lang->execution->burn = 'Burndown'; $lang->execution->computeBurn = 'Aktualisieren'; +$lang->execution->CFD = 'Cumulative Flow diagrams'; +$lang->execution->computeCFD = 'Compute Cumulative Flow diagrams'; $lang->execution->burnData = 'Burndown Daten'; $lang->execution->fixFirst = 'Bearbeite Mannstunden des ersten Tags'; $lang->execution->team = 'Teammitglieder'; @@ -380,8 +387,8 @@ $lang->execution->errorBegin = "The start time of {$lang->execu $lang->execution->errorEnd = "The end time of {$lang->executionCommon} cannot be greater than the end time %s of the project."; $lang->execution->errorLetterProject = "The start time of stage cannot be less than the start time of the project %s."; $lang->execution->errorGreaterProject = "The end time of stage cannot be greater than the end time %s of the project."; -$lang->execution->errorCommonBegin = 'The start date of ' . $lang->executionCommon . ' "%s" should be ≥ the start date of project %s: %s.'; -$lang->execution->errorCommonEnd = 'The deadline of ' . $lang->executionCommon . ' "%s" should be ≤ the deadline of project %s: %s.'; +$lang->execution->errorCommonBegin = 'The start date of ' . $lang->executionCommon . ' should be ≥ the start date of project : %s.'; +$lang->execution->errorCommonEnd = 'The deadline of ' . $lang->executionCommon . ' should be ≤ the deadline of project : %s.'; $lang->execution->accessDenied = "Zugriff zu {$lang->executionCommon} verweigert!"; $lang->execution->tips = 'Hinweis'; $lang->execution->afterInfo = "{$lang->executionCommon} wurde erstellt. Als nächstes können Sie "; diff --git a/module/execution/lang/en.php b/module/execution/lang/en.php index 242f35f23b..9595d15d66 100644 --- a/module/execution/lang/en.php +++ b/module/execution/lang/en.php @@ -118,6 +118,7 @@ $lang->execution->relatedMember = 'Team'; $lang->execution->watermark = 'Exported by ZenTao'; $lang->execution->burnXUnit = '(Date)'; $lang->execution->burnYUnit = '(Hours)'; +$lang->execution->count = '(Count)'; $lang->execution->waitTasks = 'Waiting Tasks'; $lang->execution->viewByUser = 'By User'; $lang->execution->oneProduct = "Only one stage can be linked {$lang->productCommon}"; @@ -165,6 +166,10 @@ $lang->execution->lifeTimeList['short'] = "Short-Term"; $lang->execution->lifeTimeList['long'] = "Long-Term"; $lang->execution->lifeTimeList['ops'] = "DevOps"; +$lang->execution->cfdTypeList['story'] = "{$lang->SRCommon}"; +$lang->execution->cfdTypeList['task'] = "Task"; +$lang->execution->cfdTypeList['bug'] = "Bug"; + $lang->team = new stdclass(); $lang->team->account = 'User'; $lang->team->role = 'Role'; @@ -221,6 +226,8 @@ $lang->execution->build = 'Build List'; $lang->execution->testtask = 'Request'; $lang->execution->burn = 'Burndown'; $lang->execution->computeBurn = 'Update'; +$lang->execution->CFD = 'Cumulative Flow diagrams'; +$lang->execution->computeCFD = 'Compute Cumulative Flow diagrams'; $lang->execution->burnData = 'Burndown Data'; $lang->execution->fixFirst = 'Edit 1st-Day Estimates'; $lang->execution->team = 'Members'; @@ -380,8 +387,8 @@ $lang->execution->errorBegin = "The start time of {$lang->execu $lang->execution->errorEnd = "The end time of {$lang->executionCommon} cannot be greater than the end time %s of the project."; $lang->execution->errorLetterProject = "The start time of stage cannot be less than the start time of the project %s."; $lang->execution->errorGreaterProject = "The end time of stage cannot be greater than the end time %s of the project."; -$lang->execution->errorCommonBegin = 'The start date of ' . $lang->executionCommon . ' "%s" should be ≥ the start date of project "%s": %s.'; -$lang->execution->errorCommonEnd = 'The deadline of ' . $lang->executionCommon . ' "%s" should be ≤ the deadline of project "%s": %s.'; +$lang->execution->errorCommonBegin = 'The start date of ' . $lang->executionCommon . ' should be ≥ the start date of project : %s.'; +$lang->execution->errorCommonEnd = 'The deadline of ' . $lang->executionCommon . ' should be ≤ the deadline of project : %s.'; $lang->execution->accessDenied = "Your access to {$lang->executionCommon} is denied!"; $lang->execution->tips = 'Note'; $lang->execution->afterInfo = "{$lang->executionCommon} is created. Next you can "; diff --git a/module/execution/lang/fr.php b/module/execution/lang/fr.php index 2c882fcda4..984b261d54 100644 --- a/module/execution/lang/fr.php +++ b/module/execution/lang/fr.php @@ -118,6 +118,7 @@ $lang->execution->relatedMember = 'Equipe'; $lang->execution->watermark = 'Exporté par ZenTao'; $lang->execution->burnXUnit = '(Date)'; $lang->execution->burnYUnit = '(Hours)'; +$lang->execution->count = '(Count)'; $lang->execution->waitTasks = 'Waiting Tasks'; $lang->execution->viewByUser = 'Par Utilisateur'; $lang->execution->oneProduct = "Only one stage can be linked {$lang->productCommon}"; @@ -165,6 +166,10 @@ $lang->execution->lifeTimeList['short'] = "Short-Term"; $lang->execution->lifeTimeList['long'] = "Long-Term"; $lang->execution->lifeTimeList['ops'] = "DevOps"; +$lang->execution->cfdTypeList['story'] = "{$lang->SRCommon}"; +$lang->execution->cfdTypeList['task'] = "Task"; +$lang->execution->cfdTypeList['bug'] = "Bug"; + $lang->team = new stdclass(); $lang->team->account = 'Utilisateur'; $lang->team->role = 'Rôle'; @@ -221,6 +226,8 @@ $lang->execution->build = 'Liste Builds'; $lang->execution->testtask = 'Recette'; $lang->execution->burn = ' Atterrissage'; $lang->execution->computeBurn = 'Calculer'; +$lang->execution->CFD = 'Cumulative Flow diagrams'; +$lang->execution->computeCFD = 'Compute Cumulative Flow diagrams'; $lang->execution->burnData = "Données d'atterrissage"; $lang->execution->fixFirst = 'Fixer 1er-Jour Estimation'; $lang->execution->team = 'Membres'; @@ -284,16 +291,19 @@ $lang->execution->taskKanban = 'Task Kanban'; $lang->execution->RDKanban = 'Research & Development Kanban'; /* Group browsing. */ -$lang->execution->allTasks = 'Voir Toutes'; +$lang->execution->allTasks = 'Toutes'; $lang->execution->assignedToMe = 'à Moi'; -$lang->execution->myInvolved = "Où j'ai participé"; -$lang->execution->assignedByMe = 'AssignedByMe'; +$lang->execution->myInvolved = "Ma part"; +$lang->execution->assignedByMe = 'Assignée par moi'; $lang->execution->statusSelects[''] = 'Plus...'; $lang->execution->statusSelects['wait'] = 'En Attente'; $lang->execution->statusSelects['doing'] = 'En Cours'; $lang->execution->statusSelects['undone'] = 'Non terminées'; +$lang->execution->statusSelects['myinvolved'] = $lang->execution->myInvolved; $lang->execution->statusSelects['finishedbyme'] = 'Terminées par moi'; +$lang->execution->statusSelects['assignedbyme'] = $lang->execution->assignedByMe; +$lang->execution->statusSelects['needconfirm'] = 'A confirmer'; $lang->execution->statusSelects['done'] = 'Faites'; $lang->execution->statusSelects['closed'] = 'Fermées'; $lang->execution->statusSelects['cancel'] = 'Annulées'; @@ -380,8 +390,8 @@ $lang->execution->errorBegin = "The start time of {$lang->execu $lang->execution->errorEnd = "The end time of {$lang->executionCommon} cannot be greater than the end time %s of the project."; $lang->execution->errorLetterProject = "The start time of stage cannot be less than the start time of the project %s."; $lang->execution->errorGreaterProject = "The end time of stage cannot be greater than the end time %s of the project."; -$lang->execution->errorCommonBegin = 'The start date of ' . $lang->executionCommon . ' "%s" should be ≥ the start date of project %s: %s.'; -$lang->execution->errorCommonEnd = 'The deadline of ' . $lang->executionCommon . ' "%s" should be ≤ the deadline of project %s: %s.'; +$lang->execution->errorCommonBegin = 'The start date of ' . $lang->executionCommon . ' should be ≥ the start date of project : %s.'; +$lang->execution->errorCommonEnd = 'The deadline of ' . $lang->executionCommon . ' should be ≤ the deadline of project : %s.'; $lang->execution->accessDenied = "Votre accès au {$lang->executionCommon} est refusé ! Désolé."; $lang->execution->tips = 'Note'; $lang->execution->afterInfo = "Le {$lang->executionCommon} a été créé avec succès ! Ensuite vous pouvez "; @@ -476,9 +486,6 @@ $lang->execution->typeList['kanban'] = 'Kanban'; $lang->execution->featureBar['task']['all'] = $lang->execution->allTasks; $lang->execution->featureBar['task']['unclosed'] = $lang->execution->unclosed; $lang->execution->featureBar['task']['assignedtome'] = $lang->execution->assignedToMe; -$lang->execution->featureBar['task']['myinvolved'] = $lang->execution->myInvolved; -$lang->execution->featureBar['task']['assignedbyme'] = $lang->execution->assignedByMe; -$lang->execution->featureBar['task']['needconfirm'] = 'A confirmer'; $lang->execution->featureBar['task']['status'] = $lang->execution->statusSelects['']; $lang->execution->featureBar['all']['all'] = $lang->execution->all; diff --git a/module/execution/lang/vi.php b/module/execution/lang/vi.php index 766a66f77f..c1f02f6280 100644 --- a/module/execution/lang/vi.php +++ b/module/execution/lang/vi.php @@ -337,6 +337,8 @@ $lang->execution->unfinishedExecution = "This {$lang->executionCommon} h $lang->execution->unfinishedTask = "[%s] unfinished tasks. "; $lang->execution->unresolvedBug = "[%s] unresolved bugs. "; $lang->execution->projectNotEmpty = 'Project cannot be empty.'; +$lang->execution->errorCommonBegin = 'The start date of ' . $lang->executionCommon . ' should be ≥ the start date of project : %s.'; +$lang->execution->errorCommonEnd = 'The deadline of ' . $lang->executionCommon . ' should be ≤ the deadline of project : %s.'; /* Statistics. */ $lang->execution->charts = new stdclass(); diff --git a/module/execution/lang/zh-cn.php b/module/execution/lang/zh-cn.php index b29446e64e..4438833e1e 100644 --- a/module/execution/lang/zh-cn.php +++ b/module/execution/lang/zh-cn.php @@ -118,6 +118,7 @@ $lang->execution->relatedMember = '相关成员'; $lang->execution->watermark = '由禅道导出'; $lang->execution->burnXUnit = '(日期)'; $lang->execution->burnYUnit = '(工时)'; +$lang->execution->count = '(数量)'; $lang->execution->waitTasks = '待处理'; $lang->execution->viewByUser = '按用户查看'; $lang->execution->oneProduct = "阶段只能关联一个{$lang->productCommon}"; @@ -165,6 +166,10 @@ $lang->execution->lifeTimeList['short'] = "短期"; $lang->execution->lifeTimeList['long'] = "长期"; $lang->execution->lifeTimeList['ops'] = "运维"; +$lang->execution->cfdTypeList['story'] = "{$lang->SRCommon}"; +$lang->execution->cfdTypeList['task'] = "任务"; +$lang->execution->cfdTypeList['bug'] = "Bug"; + $lang->team = new stdclass(); $lang->team->account = '用户'; $lang->team->role = '角色'; @@ -221,6 +226,8 @@ $lang->execution->build = '所有版本'; $lang->execution->testtask = '测试单'; $lang->execution->burn = '燃尽图'; $lang->execution->computeBurn = '更新燃尽图'; +$lang->execution->CFD = '累积流图'; +$lang->execution->computeCFD = '更新累积流图'; $lang->execution->burnData = '燃尽图数据'; $lang->execution->fixFirst = '修改首天工时'; $lang->execution->team = '团队成员'; @@ -380,8 +387,8 @@ $lang->execution->errorBegin = "{$lang->executionCommon}的开 $lang->execution->errorEnd = "{$lang->executionCommon}的截止时间不能大于所属项目的结束时间%s。"; $lang->execution->errorLetterProject = "阶段的计划开始时间不能小于所属项目的计划开始时间%s。"; $lang->execution->errorGreaterProject = "阶段的计划完成时间不能大于所属项目的计划完成时间%s。"; -$lang->execution->errorCommonBegin = $lang->executionCommon . '“%s”开始日期应大于等于项目“%s”的开始日期:%s。'; -$lang->execution->errorCommonEnd = $lang->executionCommon . '“%s”截止日期应小于等于项目“%s”的截止日期:%s。'; +$lang->execution->errorCommonBegin = $lang->executionCommon . '开始日期应大于等于项目的开始日期:%s。'; +$lang->execution->errorCommonEnd = $lang->executionCommon . '截止日期应小于等于项目的截止日期:%s。'; $lang->execution->accessDenied = "您无权访问该{$lang->executionCommon}!"; $lang->execution->tips = '提示'; $lang->execution->afterInfo = "{$lang->executionCommon}添加成功,您现在可以进行以下操作:"; diff --git a/module/execution/model.php b/module/execution/model.php index bcfe9f25f4..5a82330dfb 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -68,6 +68,7 @@ class executionModel extends model { $this->lang->execution->menu = new stdclass(); $this->lang->execution->menu->kanban = array('link' => "{$this->lang->kanban->common}|execution|kanban|executionID=%s"); + $this->lang->execution->menu->CFD = array('link' => "{$this->lang->execution->CFD}|execution|cfd|executionID=%s"); $this->lang->execution->menu->build = array('link' => "{$this->lang->build->common}|execution|build|executionID=%s"); $this->lang->execution->dividerMenu = ''; $this->lang->execution->accessDenied = str_replace($this->lang->executionCommon, $this->lang->execution->kanban, $this->lang->execution->accessDenied); @@ -305,7 +306,7 @@ class executionModel extends model return false; } - if($this->config->systemMode == 'new') $this->checkBeginAndEndDate($_POST['project'], $_POST['begin'], $_POST['end'], $_POST['name']); + if($this->config->systemMode == 'new') $this->checkBeginAndEndDate($_POST['project'], $_POST['begin'], $_POST['end']); if(dao::isError()) return false; /* Determine whether to add a sprint or a stage according to the model of the execution. */ @@ -500,7 +501,7 @@ class executionModel extends model if(in_array($execution->status, array('closed', 'suspended'))) $this->computeBurn($executionID); - if($this->config->systemMode == 'new' and (empty($execution->project) or $execution->project == $oldExecution->project)) $this->checkBeginAndEndDate($oldExecution->project, $execution->begin, $execution->end, $execution->name); + if($this->config->systemMode == 'new' and (empty($execution->project) or $execution->project == $oldExecution->project)) $this->checkBeginAndEndDate($oldExecution->project, $execution->begin, $execution->end); if(dao::isError()) return false; /* Child stage inherits parent stage permissions. */ @@ -869,7 +870,7 @@ class executionModel extends model ->remove('comment') ->get(); - if($this->config->systemMode == 'new') $this->checkBeginAndEndDate($oldExecution->project, $execution->begin, $execution->end, $oldExecution->name); + if($this->config->systemMode == 'new') $this->checkBeginAndEndDate($oldExecution->project, $execution->begin, $execution->end); if(dao::isError()) return false; $execution = $this->loadModel('file')->processImgURL($execution, $this->config->execution->editor->putoff['id'], $this->post->uid); @@ -1117,16 +1118,15 @@ class executionModel extends model * @param int $projectID * @param string $begin * @param string $end - * @param string $executionName * @access public * @return void */ - public function checkBeginAndEndDate($projectID, $begin, $end, $executionName) + public function checkBeginAndEndDate($projectID, $begin, $end) { $project = $this->loadModel('project')->getByID($projectID); - if($begin < $project->begin) dao::$errors['begin'] = sprintf($this->lang->execution->errorCommonBegin, $executionName, $project->name, $project->begin); - if($end > $project->end) dao::$errors['end'] = sprintf($this->lang->execution->errorCommonEnd, $executionName, $project->name, $project->end); + if($begin < $project->begin) dao::$errors['begin'] = sprintf($this->lang->execution->errorCommonBegin, $project->begin); + if($end > $project->end) dao::$errors['end'] = sprintf($this->lang->execution->errorCommonEnd, $project->end); } /* @@ -2998,6 +2998,75 @@ class executionModel extends model return $burns; } + /** + * Compute cfd of a execution. + * + * @param int $executionID + * @access public + * @return array + */ + public function computeCFD($executionID = 0, $date = '') + { + $today = $date ? $date : helper::today(); + $executions = $this->dao->select('id, code')->from(TABLE_EXECUTION) + ->where('type')->eq('kanban') + ->andWhere('status')->notin('done,closed,suspended') + ->beginIF($executionID)->andWhere('id')->in($executionID)->fi() + ->fetchPairs(); + if(!$executions) return array(); + + /* Update today's data of cfd. */ + $cells = $this->dao->select("t1.id, t1.kanban as execution, t1.`column`, t1.type, t1.cards, t1.lane, t2.name, t2.parent") + ->from(TABLE_KANBANCELL)->alias('t1') + ->leftJoin(TABLE_KANBANCOLUMN)->alias('t2')->on('t1.column = t2.id') + ->where('t1.kanban')->in(array_keys($executions)) + ->andWhere('t2.deleted')->eq('0') + ->andWhere('t1.type')->in('story,bug,task') + ->orderBy('t2.id asc') + ->fetchAll('id'); + + /* Group by execution/type/name/lane/column. */ + $columnGroup = array(); + $parentNames = array(); + foreach($cells as $id => $column) + { + if($column->parent == '-1') + { + $parentNames[$column->column] = $column->name; + continue; + } + + $column->name = isset($parentNames[$column->parent]) ? $parentNames[$column->parent] . "($column->name)" : $column->name; + $columnGroup[$column->execution][$column->type][$column->name][$column->lane][$column->column] = $column; + } + + foreach($columnGroup as $executionID => $executionGroup) + { + foreach($executionGroup as $type => $columns) + { + foreach($columns as $colName => $laneGroup) + { + $cfd = new stdclass(); + $cfd->count = 0; + $cfd->date = $today; + $cfd->type = $type; + foreach($laneGroup as $laneID => $columnGroup) + { + foreach($columnGroup as $colID => $columnCard) + { + $cards = trim($columnCard->cards, ','); + $cfd->count += $cards ? count(explode(',', $cards)) : 0; + } + } + + $cfd->name = $colName; + $cfd->execution = $executionID; + $this->dao->replace(TABLE_CFD)->data($cfd)->exec(); + } + } + } + } + /** * Fix burn for first day. * @@ -3023,6 +3092,36 @@ class executionModel extends model $this->dao->replace(TABLE_BURN)->data($data)->exec(); } + /** + * Get begin and end for CFD. + * + * @param object $execution + * @access public + * @return void + */ + public function getBeginEnd4CFD($execution) + { + $begin = $execution->begin; + $end = $execution->end; + if(helper::today() < $execution->begin) + { + $begin = helper::today(); + $end = helper::today(); + } + elseif((helper::today() >= $execution->begin) and (helper::today() <= $execution->end)) + { + $begin = (date('Y-m-d', strtotime('-14 days')) < $execution->begin) ? $execution->begin : date('Y-m-d', strtotime('-14 days')); + $end = helper::today(); + } + elseif((helper::today() > $execution->end)) + { + $begin = date($execution->end, strtotime('-14 days')) > $execution->begin ? date($execution->end, strtotime('-14 days')) : $execution->begin; + $end = $execution->end; + } + + return array($begin, $end); + } + /** * Get burn data for flot * @@ -3135,6 +3234,66 @@ class executionModel extends model if($todayTag > $counts) return array_slice($sets, $todayTag - $counts, $counts); } + /** + * Build CFD data. + * + * @param int $executionID + * @param string $type + * @param array $dateList + * @access public + * @return array + */ + public function buildCFDData($executionID, $dateList, $type) + { + $this->loadModel('report'); + $setGroup = $this->getCFDData($executionID, $dateList, $type); + + if(empty($setGroup)) return array(); + + $chartData['labels'] = $this->report->convertFormat($dateList, DT_DATE5); + $chartData['line'] = array(); + + foreach($setGroup as $name => $sets) + { + $chartData['line'][$name] = $this->report->createSingleJSON($sets, $dateList); + } + + return $chartData; + } + + /** + * Get CFD data to display. + * + * @param int $executionID + * @param string $type + * @param array $dateList + * @access public + * @return array + */ + public function getCFDData($executionID = 0, $dateList = array(), $type = 'story') + { + $execution = $this->getById($executionID); + + $setGroup = $this->dao->select("date, `count` AS value, `name`")->from(TABLE_CFD) + ->where('execution')->eq((int)$executionID) + ->andWhere('type')->eq($type) + ->andWhere('date')->in($dateList) + ->orderBy('date DESC, id asc')->fetchGroup('name', 'date'); + + $data = array(); + foreach($setGroup as $name => $sets) + { + foreach($sets as $date => $set) + { + if($date < $execution->begin) continue; + + $data[$name][$date] = $set; + } + } + + return $data; + } + /** * Get taskes by search. * diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index 844a412c43..5c9cc4abb9 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -73,12 +73,14 @@ js::set('isCNLang', !$this->loadModel('common')->checkNotCN())

execution->noExecutions : $lang->execution->noExecution;?> - - createLink('programplan', 'create', "projectID=$projectID&productID=$productID"), " " . $lang->programplan->create, '', "class='btn btn-info'");?> - - - createLink('execution', 'create', "projectID=$projectID"), " " . (($from == 'execution' and $config->systemMode == 'new') ? $lang->execution->createExec : $lang->execution->create), '', "class='btn btn-info' data-app='execution'");?> - + + + createLink('programplan', 'create', "projectID=$projectID&productID=$productID"), " " . $lang->programplan->create, '', "class='btn btn-info'");?> + + + createLink('execution', 'create', "projectID=$projectID"), " " . (($from == 'execution' and $config->systemMode == 'new') ? $lang->execution->createExec : $lang->execution->create), '', "class='btn btn-info' data-app='execution'");?> + +

diff --git a/module/execution/view/cfd.html.php b/module/execution/view/cfd.html.php new file mode 100644 index 0000000000..f0d6282880 --- /dev/null +++ b/module/execution/view/cfd.html.php @@ -0,0 +1,113 @@ + + * @package execution + * @version $Id: cfd.html.php 4164 2013-01-20 08:27:55Z wwccss $ + * @link http://www.zentao.net + */ +?> + + + + + +
+

execution->cfdTypeList, $type) . $lang->execution->CFD;?>

+
+
+
execution->count;?>
+
execution->burnXUnit;?>
+
+
+ + + + + + diff --git a/module/execution/view/create.html.php b/module/execution/view/create.html.php index 3a671c7a24..b83a4d36e3 100644 --- a/module/execution/view/create.html.php +++ b/module/execution/view/create.html.php @@ -45,6 +45,9 @@ systemMode);?> + +execution->cancelCopy);?> +execution->copyNoExecution);?>
@@ -265,7 +268,10 @@
$value) { - $this->story->printCell($value, $story, $users, '', $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table', '', $execution, $showBranch); + $this->story->printCell($value, $story, $users, $branchOption, $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table', '', $execution, $showBranch); } ?> diff --git a/module/execution/view/task.html.php b/module/execution/view/task.html.php index f254069896..fe53a70b9b 100644 --- a/module/execution/view/task.html.php +++ b/module/execution/view/task.html.php @@ -198,7 +198,7 @@ body {margin-bottom: 25px;}

task->noTask;?> - + " . $lang->task->create, '', "class='btn btn-info'");?>

diff --git a/module/execution/view/testcase.html.php b/module/execution/view/testcase.html.php index 56ef3d6e4e..908ad4c967 100644 --- a/module/execution/view/testcase.html.php +++ b/module/execution/view/testcase.html.php @@ -52,7 +52,7 @@
- + - + @@ -43,8 +46,8 @@ diff --git a/module/gitlab/view/browsegroup.html.php b/module/gitlab/view/browsegroup.html.php index c16fb9ad8b..cb0a0e07f6 100644 --- a/module/gitlab/view/browsegroup.html.php +++ b/module/gitlab/view/browsegroup.html.php @@ -12,8 +12,12 @@ ?> diff --git a/module/gitlab/view/browseproject.html.php b/module/gitlab/view/browseproject.html.php index 0acb2fa888..286ff6c9a7 100644 --- a/module/gitlab/view/browseproject.html.php +++ b/module/gitlab/view/browseproject.html.php @@ -14,19 +14,12 @@ recTotal}&recPerPage={$pager->recPerPage}&pageID=1")?> - + @@ -67,15 +60,13 @@ diff --git a/module/gitlab/view/browseuser.html.php b/module/gitlab/view/browseuser.html.php index e839d2f8b7..12ba265311 100644 --- a/module/gitlab/view/browseuser.html.php +++ b/module/gitlab/view/browseuser.html.php @@ -12,8 +12,12 @@ ?> diff --git a/module/gitlab/view/createuser.html.php b/module/gitlab/view/createuser.html.php index 0be85a7bae..5adf9ff875 100644 --- a/module/gitlab/view/createuser.html.php +++ b/module/gitlab/view/createuser.html.php @@ -11,6 +11,7 @@ */ ?> +
diff --git a/module/group/lang/de.php b/module/group/lang/de.php index ac28a47962..9deaa69598 100644 --- a/module/group/lang/de.php +++ b/module/group/lang/de.php @@ -23,7 +23,7 @@ $lang->group->byModuleTips = '(SHIFT/STRG für Multi-Se $lang->group->allTips = 'After checking this option, the administrator can manage all objects in the system, including objects created later.'; $lang->group->manageMember = 'Mitglieder'; $lang->group->manageProjectAdmin = 'Manage Program Admins'; -$lang->group->confirmDelete = 'Möchten Sie die Gruppe löschen?'; +$lang->group->confirmDelete = "Do you want to delete '%s'?"; $lang->group->successSaved = 'Gespeichert!'; $lang->group->errorNotSaved = 'Fehlgeschlagen. Bitte aktion und Gruppe wählen.'; $lang->group->viewList = 'Anzeige ist zulässig.'; @@ -45,6 +45,7 @@ $lang->group->project = 'Project'; $lang->group->group = 'Group'; $lang->group->more = 'More'; $lang->group->allCheck = 'All'; +$lang->group->noGroup = 'No group'; global $config; if($config->systemMode == 'new') $lang->group->noneProject = 'No Project'; diff --git a/module/group/lang/en.php b/module/group/lang/en.php index a2e5ba397a..86ffacb8fa 100644 --- a/module/group/lang/en.php +++ b/module/group/lang/en.php @@ -45,6 +45,7 @@ $lang->group->project = 'Project'; $lang->group->group = 'Group'; $lang->group->more = 'More'; $lang->group->allCheck = 'All'; +$lang->group->noGroup = 'No group'; global $config; if($config->systemMode == 'new') $lang->group->noneProject = 'No Project'; diff --git a/module/group/lang/fr.php b/module/group/lang/fr.php index 112481f2df..4dcbd75943 100644 --- a/module/group/lang/fr.php +++ b/module/group/lang/fr.php @@ -23,7 +23,7 @@ $lang->group->byModuleTips = '(Shift/Ctrl pour sélecti $lang->group->allTips = 'After checking this option, the administrator can manage all objects in the system, including objects created later.'; $lang->group->manageMember = 'Gérer Membres'; $lang->group->manageProjectAdmin = 'Manage Program Admins'; -$lang->group->confirmDelete = "Voulez-vous supprimer ce groupe d'utilisateurs ?"; +$lang->group->confirmDelete = "Voulez - vous supprimer '%s'?"; $lang->group->successSaved = 'Sauvé.'; $lang->group->errorNotSaved = 'Echec. Veuillez sélectionner actions et groupes.'; $lang->group->viewList = 'Accès Consultation'; @@ -45,6 +45,7 @@ $lang->group->project = 'Project'; $lang->group->group = 'Group'; $lang->group->more = 'More'; $lang->group->allCheck = 'All'; +$lang->group->noGroup = 'Aucun groupe'; global $config; if($config->systemMode == 'new') $lang->group->noneProject = 'No Project'; diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 7b018eb9b1..ba67f94a53 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -68,6 +68,7 @@ $lang->moduleOrder[210] = 'dev'; $lang->moduleOrder[215] = 'message'; $lang->moduleOrder[220] = 'gitlab'; $lang->moduleOrder[225] = 'mr'; +$lang->moduleOrder[230] = 'app'; $lang->resource = new stdclass(); @@ -734,6 +735,8 @@ $lang->resource->execution->bug = 'bug'; $lang->resource->execution->testreport = 'testreport'; $lang->resource->execution->burn = 'burn'; $lang->resource->execution->computeBurn = 'computeBurnAction'; +$lang->resource->execution->cfd = 'CFD'; +$lang->resource->execution->computeCFD = 'computeCFD'; $lang->resource->execution->fixFirst = 'fixFirst'; $lang->resource->execution->burnData = 'burnData'; $lang->resource->execution->team = 'teamAction'; @@ -792,6 +795,8 @@ $lang->execution->methodOrder[115] = 'testtask'; $lang->execution->methodOrder[120] = 'testreport'; $lang->execution->methodOrder[125] = 'burn'; $lang->execution->methodOrder[130] = 'computeBurn'; +$lang->execution->methodOrder[132] = 'cfd'; +$lang->execution->methodOrder[133] = 'computeCFD'; $lang->execution->methodOrder[135] = 'fixFirst'; $lang->execution->methodOrder[140] = 'burnData'; $lang->execution->methodOrder[145] = 'team'; @@ -1437,6 +1442,12 @@ $lang->mr->methodOrder[85] = 'close'; $lang->mr->methodOrder[90] = 'reopen'; $lang->mr->methodOrder[95] = 'addReview'; +/* App. */ +$lang->resource->app = new stdclass(); +$lang->resource->app->serverlink = 'serverLink'; + +$lang->app->methodOrder[10] = 'link'; + /* Git. */ $lang->resource->git = new stdclass(); $lang->resource->git->diff = 'diff'; diff --git a/module/group/lang/zh-cn.php b/module/group/lang/zh-cn.php index c3ffb208aa..7f1da7924f 100644 --- a/module/group/lang/zh-cn.php +++ b/module/group/lang/zh-cn.php @@ -45,6 +45,7 @@ $lang->group->project = '项目'; $lang->group->group = '分组'; $lang->group->more = '更多'; $lang->group->allCheck = '全部'; +$lang->group->noGroup = '暂时没有分组。'; global $config; if($config->systemMode == 'new') $lang->group->noneProject = '暂时没有项目'; diff --git a/module/group/view/browse.html.php b/module/group/view/browse.html.php index ab349fafe6..f3414dc39c 100644 --- a/module/group/view/browse.html.php +++ b/module/group/view/browse.html.php @@ -67,9 +67,9 @@ } else { - $deleteURL = $this->createLink('group', 'delete', "groupID=$group->id&confirm=yes"); - js::set("confirmDelete{$group->id}", sprintf($lang->group->confirmDelete, $group->name)); - echo html::a("javascript:ajaxDelete(\"$deleteURL\", \"groupList\", confirmDelete{$group->id})", '', '', "title='{$lang->group->delete}' class='btn'"); + $deleteURL = $this->createLink('group', 'delete', "groupID=$group->id&confirm=yes"); + $confirmDelete = htmlspecialchars(sprintf($lang->group->confirmDelete, $group->name)); + echo html::a("javascript:ajaxDelete(\"$deleteURL\", \"groupList\", \"$confirmDelete\")", '', '', "title='{$lang->group->delete}' class='btn'"); } } ?> diff --git a/module/index/css/index.css b/module/index/css/index.css index 185b6fb9cc..1ae12da38f 100644 --- a/module/index/css/index.css +++ b/module/index/css/index.css @@ -49,7 +49,8 @@ body.menu-hide {padding-left: 0;} .app-container {position: absolute; left: 0; bottom: 40px; right: 0; top: 0; background-color: #efefef;} .menu-hide #apps {left: 40px;} .app-container.loading:before {background-color: rgba(0,0,0,.1);} -.app-container.loading:before, .app-container.loading::after {transition-delay: 1s;} +.app-container.loading:before, .app-container.loading::after {transition-delay: 3s;} +.app-container.loading.open-from-hidden {transition: 0s;} #appsBar {position: fixed; left: 96px; bottom: 0; right: 0; height: 40px; z-index: 1012; background: #fff; border-top: 1px solid #eff1f7;} .menu-hide #appsBar {left: 40px;} diff --git a/module/index/css/index.en.css b/module/index/css/index.en.css index ac1227a07e..c008c4a5df 100644 --- a/module/index/css/index.en.css +++ b/module/index/css/index.en.css @@ -1 +1,2 @@ +#apps { left: 106px;} #menu { width: 106px;} diff --git a/module/index/js/index.js b/module/index/js/index.js index 3ae31f534a..3963a1a809 100644 --- a/module/index/js/index.js +++ b/module/index/js/index.js @@ -264,7 +264,11 @@ } /* Show page app and update iframe source */ - if(url) reloadApp(appCode, url, true); + if (url) + { + app.$app.toggleClass('open-from-hidden', app.$app.is(':hidden')) + reloadApp(appCode, url, true); + } app.zIndex = openedAppZIndex++; app.$app.show().css('z-index', app.zIndex); @@ -463,7 +467,7 @@ { app.$app.removeClass('loading'); app._loadTimer = null; - }, 10000); + }, 15000); } /** diff --git a/module/install/view/step5.html.php b/module/install/view/step5.html.php index c438a8aae7..a8bb9b72c7 100644 --- a/module/install/view/step5.html.php +++ b/module/install/view/step5.html.php @@ -61,7 +61,7 @@
- + diff --git a/module/jenkins/control.php b/module/jenkins/control.php index 129e6830ca..38b306e482 100644 --- a/module/jenkins/control.php +++ b/module/jenkins/control.php @@ -35,8 +35,6 @@ class jenkins extends control */ public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { - if(common::hasPriv('jenkins', 'create')) $this->lang->TRActions = html::a(helper::createLink('jenkins', 'create'), " " . $this->lang->jenkins->create, '', "class='btn btn-primary'"); - $this->app->loadClass('pager', $static = true); $pager = new pager($recTotal, $recPerPage, $pageID); diff --git a/module/jenkins/lang/de.php b/module/jenkins/lang/de.php index 1f4f3135ee..be3af99b70 100644 --- a/module/jenkins/lang/de.php +++ b/module/jenkins/lang/de.php @@ -20,6 +20,7 @@ $lang->jenkins->lblCreate = 'Create Jenkins Server'; $lang->jenkins->desc = 'Description'; $lang->jenkins->tokenFirst = 'Use token if not empty.'; $lang->jenkins->tips = 'Cancel "Prevent Cross Site Request Forgery exploits" when using password.'; +$lang->jenkins->serverList = 'Server List'; $lang->jenkins->error = new stdclass(); $lang->jenkins->error->linkedJob = 'Failed. This jenkins has associated with the compile.'; diff --git a/module/jenkins/lang/en.php b/module/jenkins/lang/en.php index 4fad34c13e..69606a9447 100644 --- a/module/jenkins/lang/en.php +++ b/module/jenkins/lang/en.php @@ -20,6 +20,7 @@ $lang->jenkins->lblCreate = 'Create Jenkins Server'; $lang->jenkins->desc = 'Description'; $lang->jenkins->tokenFirst = 'Use token if not empty.'; $lang->jenkins->tips = 'Cancel "Prevent Cross Site Request Forgery exploits" when using password.'; +$lang->jenkins->serverList = 'Server List'; $lang->jenkins->error = new stdclass(); $lang->jenkins->error->linkedJob = 'Failed. This jenkins has associated with the compile.'; diff --git a/module/jenkins/lang/fr.php b/module/jenkins/lang/fr.php index 49ec96c6c8..323869d422 100644 --- a/module/jenkins/lang/fr.php +++ b/module/jenkins/lang/fr.php @@ -20,6 +20,7 @@ $lang->jenkins->lblCreate = 'Cr閑r Serveur Jenkins'; $lang->jenkins->desc = 'Description'; $lang->jenkins->tokenFirst = 'Utiliser un Token si non vide.'; $lang->jenkins->tips = 'Cancel "Prevent Cross Site Request Forgery exploits" when using password.'; +$lang->jenkins->serverList = 'Server List'; $lang->jenkins->error = new stdclass(); $lang->jenkins->error->linkedJob = 'Failed. This jenkins has associated with the compile.'; diff --git a/module/jenkins/lang/vi.php b/module/jenkins/lang/vi.php index b5a5f5d46d..6a9b3858ee 100644 --- a/module/jenkins/lang/vi.php +++ b/module/jenkins/lang/vi.php @@ -17,3 +17,4 @@ $lang->jenkins->lblCreate = 'Tạo Jenkins Server'; $lang->jenkins->desc = 'Mô tả'; $lang->jenkins->tokenFirst = 'Sử dụng token nếu không trống.'; $lang->jenkins->tips = 'Hủy "Ngăn chặn khai thác yêu cầu trang web giả mạo" khi sử dụng mật khẩu.'; +$lang->jenkins->serverList = 'Server List'; diff --git a/module/jenkins/lang/zh-cn.php b/module/jenkins/lang/zh-cn.php index fc530fa5cc..c2dd47587e 100644 --- a/module/jenkins/lang/zh-cn.php +++ b/module/jenkins/lang/zh-cn.php @@ -20,6 +20,7 @@ $lang->jenkins->lblCreate = '添加Jenkins服务器'; $lang->jenkins->desc = '描述'; $lang->jenkins->tokenFirst = 'Token不为空时,优先使用Token。'; $lang->jenkins->tips = '使用密码时,请在Jenkins全局安全设置中禁用"防止跨站点请求伪造"选项。'; +$lang->jenkins->serverList = '服务器列表'; $lang->jenkins->error = new stdclass(); $lang->jenkins->error->linkedJob = '删除失败,该Jenkins跟构建有关联,请取消关联或删除构建。'; diff --git a/module/jenkins/lang/zh-tw.php b/module/jenkins/lang/zh-tw.php index 6ce5017741..68ad3552f6 100644 --- a/module/jenkins/lang/zh-tw.php +++ b/module/jenkins/lang/zh-tw.php @@ -20,6 +20,7 @@ $lang->jenkins->lblCreate = '添加Jenkins伺服器'; $lang->jenkins->desc = '描述'; $lang->jenkins->tokenFirst = 'Token不為空時,優先使用Token。'; $lang->jenkins->tips = '使用密碼時,請在Jenkins全局安全設置中禁用"防止跨站點請求偽造"選項。'; +$lang->jenkins->serverList = '伺服器列表'; $lang->jenkins->error = new stdclass(); $lang->jenkins->error->linkedJob = '刪除失敗,該Jenkins跟構建有關聯,請取消關聯或刪除構建。'; diff --git a/module/jenkins/view/browse.html.php b/module/jenkins/view/browse.html.php index 089ff77834..dfa38962a3 100644 --- a/module/jenkins/view/browse.html.php +++ b/module/jenkins/view/browse.html.php @@ -12,9 +12,13 @@ ?>

@@ -24,7 +28,6 @@

-
diff --git a/module/job/control.php b/module/job/control.php index 967db36bd7..8b834d7008 100644 --- a/module/job/control.php +++ b/module/job/control.php @@ -22,7 +22,7 @@ class job extends control public function __construct($moduleName = '', $methodName = '') { parent::__construct($moduleName, $methodName); - $this->loadModel('ci')->setMenu(); + if($methodName != 'browse') $this->loadModel('ci')->setMenu(); $this->projectID = isset($_GET['project']) ? $_GET['project'] : 0; } @@ -36,17 +36,21 @@ class job extends control * @access public * @return void */ - public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + public function browse($repoID = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { + /* Set session. */ + $this->loadModel('ci')->setMenu($repoID); + $this->app->loadClass('pager', $static = true); $pager = new pager($recTotal, $recPerPage, $pageID); $this->app->loadLang('compile'); - $this->view->jobList = $this->job->getList($orderBy, $pager); + $this->view->jobList = $this->job->getList($repoID, $orderBy, $pager); $this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->job->browse; $this->view->position[] = $this->lang->ci->job; $this->view->position[] = $this->lang->job->browse; + $this->view->repoID = $repoID; $this->view->orderBy = $orderBy; $this->view->pager = $pager; @@ -167,7 +171,7 @@ class job extends control } $this->loadModel('action')->create('job', $id, 'edited'); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse'))); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse', "repoID={$job->repo}"))); } $repo = $this->loadModel('repo')->getRepoByID($job->repo); diff --git a/module/job/model.php b/module/job/model.php index 6d6a85b99d..b8b0933748 100644 --- a/module/job/model.php +++ b/module/job/model.php @@ -36,17 +36,21 @@ class jobModel extends model /** * Get job list. * + * @param int $repoID * @param string $orderBy * @param object $pager + * @param string $engine + * @param string $pipeline * @access public * @return array */ - public function getList($orderBy = 'id_desc', $pager = null, $engine = '', $pipeline = '') + public function getList($repoID = 0, $orderBy = 'id_desc', $pager = null, $engine = '', $pipeline = '') { return $this->dao->select('t1.*, t2.name as repoName, t3.name as jenkinsName')->from(TABLE_JOB)->alias('t1') ->leftJoin(TABLE_REPO)->alias('t2')->on('t1.repo=t2.id') ->leftJoin(TABLE_PIPELINE)->alias('t3')->on('t1.server=t3.id') ->where('t1.deleted')->eq('0') + ->beginIF($repoID)->andWhere('t1.repo')->eq($repoID)->fi() ->beginIF($engine)->andWhere('t1.engine')->eq($engine)->fi() ->beginIF($pipeline)->andWhere('t1.pipeline')->eq($pipeline)->fi() ->orderBy($orderBy) diff --git a/module/job/view/browse.html.php b/module/job/view/browse.html.php index eac0cb5328..ec44c6dd42 100644 --- a/module/job/view/browse.html.php +++ b/module/job/view/browse.html.php @@ -13,8 +13,8 @@
diff --git a/module/kanban/config.php b/module/kanban/config.php index fc6374a1ff..27373d5b3f 100644 --- a/module/kanban/config.php +++ b/module/kanban/config.php @@ -40,7 +40,7 @@ $config->kanban->editor->createcard = array('id' => 'desc', 'tools' => 'simpl $config->kanban->editor->activate = array('id' => 'comment', 'tools' => 'simpleTools'); $config->kanban->editor->close = array('id' => 'comment', 'tools' => 'simpleTools'); $config->kanban->editor->editcard = array('id' => 'desc', 'tools' => 'simpleTools'); -$config->kanban->editor->viewcard = array('id' => 'comment', 'tools' => 'simpleTools'); +$config->kanban->editor->viewcard = array('id' => 'comment,lastComment', 'tools' => 'simpleTools'); $config->kanban->editor->activatecard = array('id' => 'comment', 'tools' => 'simpleTools'); $config->kanban->fromType = array('execution', 'productplan', 'release', 'build'); diff --git a/module/kanban/control.php b/module/kanban/control.php index 6eb6747023..022e10d78b 100644 --- a/module/kanban/control.php +++ b/module/kanban/control.php @@ -604,24 +604,30 @@ class kanban extends control /** * Delete a lane. * + * @param int $regionID + * @param int $kanbanID * @param int $laneID * @param string $confirm no|yes * @access public * @return void */ - public function deleteLane($laneID, $confirm = 'no') + public function deleteLane($regionID, $kanbanID, $laneID, $confirm = 'no') { if($confirm == 'no') { $laneType = $this->kanban->getLaneById($laneID)->type; $confirmTip = in_array($laneType, array('story', 'task', 'bug')) ? sprintf($this->lang->kanbanlane->confirmDeleteTip, $this->lang->{$laneType}->common) : $this->lang->kanbanlane->confirmDelete; - return print(js::confirm($confirmTip, $this->createLink('kanban', 'deleteLane', "laneID=$laneID&confirm=yes"), '')); + return print(js::confirm($confirmTip, $this->createLink('kanban', 'deleteLane', "regionID=$regionID&kanbanID=$kanbanID&laneID=$laneID&confirm=yes"), '')); + } else { $this->kanban->delete(TABLE_KANBANLANE, $laneID); - return print(js::reload('parent')); + + $kanbanGroup = $this->kanban->getKanbanData($kanbanID, $regionID); + $kanbanGroup = json_encode($kanbanGroup); + return print(""); } } @@ -644,7 +650,10 @@ class kanban extends control if(dao::isError()) $this->send(array('message' => dao::getError(), 'result' => 'fail')); $this->loadModel('action')->create('kanbanColumn', $columnID, 'Created'); - $this->send(array('message' => $this->lang->saveSuccess, 'result' => 'success', 'locate' => 'parent')); + + $region = $this->kanban->getRegionByID($column->region); + $kanbanGroup = $this->kanban->getKanbanData($region->kanban, $region->id); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => array('target' => 'parent', 'name' => 'updateRegion', 'params' => array($column->region, $kanbanGroup)))); } $this->view->title = $this->lang->kanban->createColumn; @@ -656,6 +665,7 @@ class kanban extends control /** * Split column. * + * @param int $columnID * @access public * @return void */ @@ -665,7 +675,11 @@ class kanban extends control { $this->kanban->splitColumn($columnID); if(dao::isError()) $this->send(array('message' => dao::getError(), 'result' => 'fail')); - $this->send(array('message' => $this->lang->saveSuccess, 'result' => 'success', 'locate' => 'parent')); + + $column = $this->kanban->getColumnById($columnID); + $region = $this->kanban->getRegionByID($column->region); + $kanbanGroup = $this->kanban->getKanbanData($region->kanban, $region->id); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => array('target' => 'parent', 'name' => 'updateRegion', 'params' => array($column->region, $kanbanGroup)))); } $this->display(); @@ -705,8 +719,10 @@ class kanban extends control $this->loadModel('action')->create('kanbancolumn', $columnID, 'archived'); - if(isonlybody()) return print(js::reload('parent.parent')); - return print(js::reload('parent')); + $region = $this->kanban->getRegionByID($column->region); + $kanbanGroup = $this->kanban->getKanbanData($region->kanban, $region->id); + $kanbanGroup = json_encode($kanbanGroup); + return print(""); } } @@ -789,7 +805,10 @@ class kanban extends control $this->dao->delete()->from(TABLE_KANBANCOLUMN)->where('id')->eq($columnID)->exec(); - return print(js::reload('parent')); + $region = $this->kanban->getRegionByID($column->region); + $kanbanGroup = $this->kanban->getKanbanData($region->kanban, $region->id); + $kanbanGroup = json_encode($kanbanGroup); + return print(""); } } @@ -1299,20 +1318,13 @@ class kanban extends control * @param int $laneID * @param int $columnID * @param string $cards - * @param int $cardID * @access public * @return void */ - public function sortCard($kanbanID, $laneID, $columnID, $cards = '', $cardID = 0) + public function sortCard($kanbanID, $laneID, $columnID, $cards = '') { if(empty($cards)) return; - if($cardID) - { - $fromCell = $this->dao->select('cards, lane, column')->from(TABLE_KANBANCELL)->where('cards')->like("%,$cardID,%")->fetch(); - if($fromCell->lane != $laneID or $fromCell->column != $columnID) return; - } - $this->dao->update(TABLE_KANBANCELL)->set('cards')->eq(",$cards,")->where('kanban')->eq($kanbanID)->andWhere('lane')->eq($laneID)->andWhere('`column`')->eq($columnID)->exec(); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); @@ -1433,8 +1445,7 @@ class kanban extends control if(isonlybody()) return print(js::reload('parent.parent')); - $card = $this->kanban->getCardByID($cardID); - $kanbanGroup = $this->kanban->getKanbanData($card->kanban, $card->region); + $kanbanGroup = $this->kanban->getKanbanData($card->kanban, $card->region); $kanbanGroupParam = json_encode($kanbanGroup); return print(""); } @@ -1495,7 +1506,9 @@ class kanban extends control return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, $regionID)")); } - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent')); + $region = $this->kanban->getRegionByID($column->region); + $kanbanGroup = $this->kanban->getKanbanData($region->kanban, $region->id); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => array('target' => 'parent', 'name' => 'updateRegion', 'params' => array($column->region, $kanbanGroup)))); } $this->app->loadLang('story'); @@ -1561,7 +1574,7 @@ class kanban extends control $this->loadModel('action')->create('kanbanlane', $laneID, 'Edited', '', $executionID); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent', 'lane' => $lane)); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => 1, 'callback' => array('target' => 'parent', 'name' => 'updateLaneName', 'params' => array($laneID, $this->post->name)))); } $lane = $this->kanban->getLaneById($laneID); @@ -1592,7 +1605,7 @@ class kanban extends control $this->loadModel('action')->create('kanbanlane', $laneID, 'Edited', '', $executionID); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent')); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => array('target' => 'parent', 'name' => 'updateLaneColor', 'params' => array($laneID, $this->post->color)))); } $lane = $this->kanban->getLaneById($laneID); @@ -1627,19 +1640,8 @@ class kanban extends control $this->action->logHistory($actionID, $changes); } - if($from == 'RDKanban') - { - if(dao::isError()) return $this->sendError(dao::getError()); - $execLaneType = $this->session->execLaneType ? $this->session->execLaneType : 'all'; - $execGroupBy = $this->session->execGroupBy ? $this->session->execGroupBy : 'default'; - $regionID = $execGroupBy == 'default' ? $column->region : 0; - $kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $execLaneType, 'id_desc', $regionID, $execGroupBy); - $kanbanData = json_encode($kanbanData); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, $regionID)")); - } - - return $this->sendSuccess(array('locate' => 'parent')); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => array('target' => 'parent', 'name' => 'updateColumnName', 'params' => array($columnID, $this->post->name, $this->post->color)))); } $this->view->canEdit = $from == 'RDKanban' ? 0 : 1; diff --git a/module/kanban/css/editspace.css b/module/kanban/css/editspace.css index 47dd3f8470..6496806503 100644 --- a/module/kanban/css/editspace.css +++ b/module/kanban/css/editspace.css @@ -1,3 +1,4 @@ #mainContent {padding-left: 0px; height: 500px;} #contactListMenu_chosen {vertical-align: unset;} #teamBox .input-group .input-group-btn {vertical-align: top;} +.chosen-container .chosen-results {max-height: 200px;} diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index 85182ef50e..b6bd322297 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -899,11 +899,59 @@ function updateRegion(regionID, regionData) return true; } +/** + * Update region name. + * + * @param int $regionID + * @param string $name + * @access public + * @return void + */ function updateRegionName(regionID, name) { $('.region[data-id="' + regionID + '"] > .region-header > strong:first').text(name); } +/** + * Update lane name. + * + * @param int $laneID + * @param string $name + * @access public + * @return void + */ +function updateLaneName(laneID, name) +{ + $('.kanban-lane[data-id="' + laneID + '"] > .kanban-lane-name > span').text(name); +} + +/** + * Update lane color. + * + * @param int $laneID + * @param string $color + * @access public + * @return void + */ +function updateLaneColor(laneID, color) +{ + $('.kanban-lane[data-id="' + laneID + '"] > .kanban-lane-name').css('background-color', color); +} + +/** + * Update column name. + * + * @param int $columnID + * @param string $name + * @param string $color + * @access public + * @return void + */ +function updateColumnName(columnID, name, color) +{ + $('.kanban-col[data-id="' + columnID + '"] > div.title > span:first').text(name).css('color', color); +} + /** * Hide kanban action */ @@ -1113,10 +1161,12 @@ function createLaneMenu(options) var privs = lane.actions; if(!privs.length) return []; - var items = []; + var items = []; + var regionID = lane.$kanbanData.region; + var kanbanID = lane.$kanbanData.kanban; if(privs.includes('editLaneName')) items.push({label: kanbanLang.editLaneName, icon: 'edit', url: createLink('kanban', 'editLaneName', 'laneID=' + lane.id + '&executionID=0&from=kanban'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '635px'}}); if(privs.includes('editLaneColor')) items.push({label: kanbanLang.editLaneColor, icon: 'color', url: createLink('kanban', 'editLaneColor', 'laneID=' + lane.id + '&executionID=0&from=kanban'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '635px'}}); - if(privs.includes('deleteLane')) items.push({label: kanbanLang.deleteLane, icon: 'trash', url: createLink('kanban', 'deleteLane', 'lane=' + lane.id), attrs: {'target': 'hiddenwin'}}); + if(privs.includes('deleteLane')) items.push({label: kanbanLang.deleteLane, icon: 'trash', url: createLink('kanban', 'deleteLane', 'regionID=' + regionID + '&kanbanID=' + kanbanID + '&lane=' + lane.id), attrs: {'target': 'hiddenwin'}}); var bounds = options.$trigger[0].getBoundingClientRect(); items.$options = {x: bounds.right, y: bounds.top}; @@ -1306,7 +1356,7 @@ function handleSortCards(event) orders.splice(orders.indexOf(fromID), 1); orders.splice(orders.indexOf(toID) + (event.insert === 'before' ? 0 : 1), 0, fromID); - var url = createLink('kanban', 'sortCard', 'kanbanID=' + kanbanID + '&laneID=' + newLaneID + '&columnID=' + newColID + '&cards=' + orders.join(',') + '&cardID=' + fromID); + var url = createLink('kanban', 'sortCard', 'kanbanID=' + kanbanID + '&laneID=' + newLaneID + '&columnID=' + newColID + '&cards=' + orders.join(',')); $.getJSON(url, function(response) { if(response.result === 'fail') diff --git a/module/kanban/model.php b/module/kanban/model.php index 6d7d1b2b8c..248dce117b 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -827,7 +827,7 @@ class kanbanModel extends model */ public function getRDKanban($executionID, $browseType = 'all', $orderBy = 'id_desc', $regionID = 0, $groupBy = 'default', $searchValue = '') { - if($groupBy != 'default') return $this->getKanban4Group($executionID, $browseType, $groupBy, $searchValue); + if($groupBy != 'default' and $groupBy != '') return $this->getKanban4Group($executionID, $browseType, $groupBy, $searchValue); $kanbanData = array(); $actions = array('sortGroup'); @@ -1479,6 +1479,19 @@ class kanbanModel extends model if($browseType == 'bug') $cardList = $this->loadModel('bug')->getExecutionBugs($executionID); if($browseType == 'task') $cardList = $this->loadModel('execution')->getKanbanTasks($executionID, "id"); + if($browseType == 'task' and $groupBy == 'assignedTo') + { + foreach($cardList as $id => $task) + { + if($task->mode == 'multi') + { + $task->team = $this->dao->select('t1.account,t2.realname')->from(TABLE_TEAM)->alias('t1') + ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account') + ->where('t1.root')->eq($id)->andWhere('t1.type')->eq('task')->orderBy('t1.order')->fetchPairs('account'); + } + } + } + /* Get objects cards menus. */ if($browseType == 'story') $storyCardMenu = $this->getKanbanCardMenu($executionID, $cardList, 'story'); if($browseType == 'bug') $bugCardMenu = $this->getKanbanCardMenu($executionID, $cardList, 'bug'); @@ -1564,13 +1577,20 @@ class kanbanModel extends model $cardData = array(); if(in_array($groupBy, array('module', 'story', 'pri', 'severity')) and (int)$object->$groupBy !== $laneID) continue; - if(in_array($groupBy, array('assignedTo', 'type', 'category', 'source')) and $object->$groupBy !== $laneID) continue; + if(in_array($groupBy, array('type', 'category', 'source')) and $object->$groupBy !== $laneID) continue; + if($groupBy == 'assignedTo') + { + if(empty($object->team) and $object->$groupBy !== $laneID) continue; + if(!empty($object->team) and !in_array($laneID, array_keys($object->team), true)) continue; + + if($object->$groupBy !== $laneID) $cardData['assignedTo'] = $laneID; + } $cardData['id'] = $object->id; $cardData['order'] = $cardOrder; $cardData['pri'] = $object->pri ? $object->pri : ''; $cardData['estimate'] = $browseType == 'bug' ? '' : $object->estimate; - $cardData['assignedTo'] = $object->assignedTo; + $cardData['assignedTo'] = empty($cardData['assignedTo']) ? $object->assignedTo : $cardData['assignedTo']; $cardData['deadline'] = $browseType == 'story' ? '' : $object->deadline; $cardData['severity'] = $browseType == 'bug' ? $object->severity : ''; @@ -1625,6 +1645,14 @@ class kanbanModel extends model foreach($cardList as $item) { if(!isset($groupByList[$item->$groupBy])) $groupByList[$item->$groupBy] = $item->$groupBy; + + if($groupBy == 'assignedTo' and !empty($item->team)) + { + foreach($item->team as $account => $name) + { + if(!isset($groupByList[$account])) $groupByList[$account] = $account; + } + } } if(in_array($groupBy, array('module', 'story', 'assignedTo'))) @@ -1734,7 +1762,6 @@ class kanbanModel extends model ->where('deleted')->eq(0) ->andWhere('id')->in($spaceIdList) ->beginIF(in_array($browseType, array('private', 'cooperation', 'public')))->andWhere('type')->eq($browseType)->fi() - ->beginIF($browseType == 'involved')->andWhere('owner')->ne($account)->fi() ->beginIF($this->cookie->showClosed == 0 and $browseType != 'showClosed')->andWhere('status')->ne('closed')->fi() ->orderBy('id_desc') ->fetchPairs('id'); @@ -1780,10 +1807,11 @@ class kanbanModel extends model $account = $this->app->user->account; foreach($objects as $objectID => $object) { - $remove = true; if($objectType == 'kanbanspace' and $object->type == 'public' and $param != 'involved') continue; - if($object->owner == $account and $param != 'involved') $remove = false; + $remove = true; + + if($object->owner == $account) $remove = false; if(strpos(",{$object->team},", ",$account,") !== false) $remove = false; if(strpos(",{$object->whitelist},", ",$account,") !== false) $remove = false; @@ -1795,7 +1823,6 @@ class kanbanModel extends model if($spaceType == 'public' and $param != 'involved') $remove = false; } - if($objectType == 'kanbanspace' and $param == 'involved' and $object->owner == $account) $remove = true; if($remove) unset($objects[$objectID]); } diff --git a/module/mail/model.php b/module/mail/model.php index 5f53254101..f060aac58a 100644 --- a/module/mail/model.php +++ b/module/mail/model.php @@ -533,7 +533,7 @@ class mailModel extends model $data->ccList = $ccList; $data->subject = $subject; $data->data = $body; - $data->createdBy = $this->config->mail->fromName; + $data->createdBy = $this->app->user->account; $data->createdDate = helper::now(); $this->dao->insert(TABLE_NOTIFY)->data($data)->autocheck()->exec(); } diff --git a/module/mr/control.php b/module/mr/control.php index af95c5b340..83fa102c98 100644 --- a/module/mr/control.php +++ b/module/mr/control.php @@ -674,8 +674,7 @@ class mr extends control { $this->product->setMenu($productID, 0); $this->config->bug->search['fields']['branch'] = $this->lang->product->branch; - $branches = array('' => '') + $this->loadModel('branch')->getPairs($productID, 'noempty'); - $this->config->bug->search['params']['branch']['values'] = $branches; + $this->config->bug->search['params']['branch']['values'] = array('' => '') + $this->loadModel('branch')->getPairs($productID, 'noempty'); } $this->loadModel('search')->setSearchParams($this->config->bug->search); diff --git a/module/mr/view/browse.html.php b/module/mr/view/browse.html.php index 129b879687..86ede0244f 100644 --- a/module/mr/view/browse.html.php +++ b/module/mr/view/browse.html.php @@ -10,14 +10,6 @@ ?> diff --git a/module/product/control.php b/module/product/control.php index 4f724735e9..1108ea3e27 100644 --- a/module/product/control.php +++ b/module/product/control.php @@ -148,18 +148,18 @@ class product extends control } /* Set menu. */ - if($this->app->tab == 'product') + if($this->app->tab == 'project') + { + $this->session->set('storyList', $this->app->getURI(true), 'project'); + $this->loadModel('project')->setMenu($projectID); + } + else { $this->session->set('storyList', $this->app->getURI(true), 'product'); $this->session->set('productList', $this->app->getURI(true), 'product'); $this->product->setMenu($productID, $branch, 0, '', "storyType=$storyType"); } - if($this->app->tab == 'project') - { - $this->session->set('storyList', $this->app->getURI(true), 'project'); - $this->loadModel('project')->setMenu($projectID); - } /* Lower browse type. */ $browseType = strtolower($browseType); diff --git a/module/product/js/all.js b/module/product/js/all.js index e3e8a72217..9d18908c92 100644 --- a/module/product/js/all.js +++ b/module/product/js/all.js @@ -60,12 +60,19 @@ $(function() }); } - /* Add a statistics prompt statement after the Edit button */ + /** + * Add a statistics prompt statement after the Edit button. + * + * @access public + * @return void + */ function addStatistic() { var checkedLength = $(":checkbox[name^='productIDList']:checked").length; var summary = checkedProducts.replace('%s', checkedLength); + if(cilentLang == "en" && checkedLength < 2) summary = summary.replace('products', 'product'); var statistic = "
" + summary + "
"; + if(checkedLength > 0) { $('#productsSummary').remove(); @@ -77,6 +84,35 @@ $(function() } } + /** + * Anti shake operation for jquery. + * + * @param fn $fn + * @param delay $delay + * @access public + * @return void + */ + function debounce(fn, delay) + { + var timer = null; + return function() + { + if(timer) clearTimeout(timer); + timer = setTimeout(fn, delay) + } + } + + /** + * Update statistics. + * + * @access public + * @return void + */ + function updateStatistic() + { + debounce(addStatistic(), 200) + } + $('#productTableList').on('click', '.row-program,.row-line', function(e) { if($(e.target).closest('.table-nest-toggle,a').length) return; @@ -96,7 +132,7 @@ $(function() { updatePrarentCheckbox($('#productTableList>tr[data-id="' + parentID + '"]')); } - addStatistic() + updateStatistic() }); $('#productListForm').on('checkChange', updateCheckboxes); @@ -104,7 +140,7 @@ $(function() $(":checkbox[name^='productIDList']").on('click', function() { - addStatistic() + updateStatistic() }); $(".check-all").on('click', function() @@ -117,6 +153,6 @@ $(function() { $(":checkbox[name^='productIDList']").prop('checked', true); } - addStatistic() + updateStatistic() }); }); diff --git a/module/product/lang/en.php b/module/product/lang/en.php index 5c30a03101..ec8f1e6c14 100644 --- a/module/product/lang/en.php +++ b/module/product/lang/en.php @@ -207,8 +207,6 @@ $lang->product->noMatched = '"%s" cannot be found.' . $lang->productCommon; $lang->product->featureBar['browse']['allstory'] = $lang->product->allStory; $lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed; $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']['reviewbyme'] = $lang->product->reviewByMe; $lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory; $lang->product->featureBar['browse']['more'] = $lang->more; @@ -217,7 +215,9 @@ $lang->product->featureBar['all']['all'] = $lang->product->allProduct; $lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed; $lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed']; +$lang->product->moreSelects['openedbyme'] = $lang->product->openedByMe; $lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe; +$lang->product->moreSelects['reviewedbyme'] = $lang->product->reviewedByMe; $lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; $lang->product->moreSelects['activestory'] = $lang->product->activeStory; $lang->product->moreSelects['changedstory'] = $lang->product->changedStory; diff --git a/module/product/view/all.html.php b/module/product/view/all.html.php index 55ff1f0cf0..0ac5a3c677 100644 --- a/module/product/view/all.html.php +++ b/module/product/view/all.html.php @@ -256,6 +256,7 @@ product->checkedProducts);?> +app->getClientLang());?> diff --git a/module/programplan/control.php b/module/programplan/control.php index fc503a4e7c..f55a7890cf 100644 --- a/module/programplan/control.php +++ b/module/programplan/control.php @@ -186,6 +186,11 @@ class programplan extends control $this->app->loadLang('project'); $this->app->loadLang('execution'); $plan = $this->programplan->getByID($planID); + + global $lang; + $lang->executionCommon = $lang->execution->stage; + include $this->app->getModulePath('', 'execution') . 'lang/' . $this->app->getClientLang() . '.php'; + if($_POST) { $changes = $this->programplan->update($planID, $projectID); diff --git a/module/programplan/model.php b/module/programplan/model.php index b0a2e30ed7..efb5b8c6ea 100755 --- a/module/programplan/model.php +++ b/module/programplan/model.php @@ -735,6 +735,10 @@ class programplanModel extends model /* Judgment of required items. */ if($plan->begin == '0000-00-00') dao::$errors['begin'][] = sprintf($this->lang->error->notempty, $this->lang->programplan->begin); if($plan->end == '0000-00-00') dao::$errors['end'][] = sprintf($this->lang->error->notempty, $this->lang->programplan->end); + if(dao::isError()) return false; + + if($projectID) $this->loadModel('execution')->checkBeginAndEndDate($projectID, $plan->begin, $plan->end); + if(dao::isError()) return false; $planChanged = ($oldPlan->name != $plan->name || $oldPlan->milestone != $plan->milestone || $oldPlan->begin != $plan->begin || $oldPlan->end != $plan->end); diff --git a/module/project/config.php b/module/project/config.php index 21224eac94..e86ae4721a 100644 --- a/module/project/config.php +++ b/module/project/config.php @@ -73,13 +73,13 @@ $config->project->datatable->fieldList['status']['pri'] = '2'; $config->project->datatable->fieldList['begin']['title'] = 'begin'; $config->project->datatable->fieldList['begin']['fixed'] = 'no'; -$config->project->datatable->fieldList['begin']['width'] = '90'; +$config->project->datatable->fieldList['begin']['width'] = '115'; $config->project->datatable->fieldList['begin']['required'] = 'no'; $config->project->datatable->fieldList['begin']['pri'] = '9'; $config->project->datatable->fieldList['end']['title'] = 'end'; $config->project->datatable->fieldList['end']['fixed'] = 'no'; -$config->project->datatable->fieldList['end']['width'] = '90'; +$config->project->datatable->fieldList['end']['width'] = '100'; $config->project->datatable->fieldList['end']['required'] = 'no'; $config->project->datatable->fieldList['end']['pri'] = '3'; diff --git a/module/project/control.php b/module/project/control.php index 5c80678579..82695213fa 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -1220,8 +1220,9 @@ class project extends control $queryID = ($type == 'bysearch') ? (int)$param : 0; $actionURL = $this->createLink('project', 'build', "projectID=$projectID&type=bysearch&queryID=myQueryID"); - $devel = $project->model == 'waterfall' ? true : false; - $executions = $this->loadModel('execution')->getByProject($projectID, 'all', '', true, $devel); + $allExecutions = $this->loadModel('execution')->getByProject($projectID, 'all', '', true); + $devel = $project->model == 'waterfall' ? true : false; + $executions = $this->loadModel('execution')->getByProject($projectID, 'all', '', true, $devel); $this->config->build->search['fields']['execution'] = $this->project->lang->executionCommon; $this->config->build->search['params']['execution'] = array('operator' => '=', 'control' => 'select', 'values' => array('' => '') + $executions); @@ -1278,6 +1279,7 @@ class project extends control $this->view->projectID = $projectID; $this->view->project = $project; $this->view->products = $products; + $this->view->allExecutions = $allExecutions; $this->view->executions = $executions; $this->view->type = $type; diff --git a/module/project/js/build.js b/module/project/js/build.js index e8a9ea9c64..86397cec51 100644 --- a/module/project/js/build.js +++ b/module/project/js/build.js @@ -4,7 +4,10 @@ $(function() { if(executions.length == 0) { - alert(createExecution); + var message = noDevStage; + if(allExecutions.length == 0) message = createExecution; + alert(message); + var link = createLink('execution', 'create', 'projectID=' + projectID); window.parent.$.apps.open(link, 'execution'); diff --git a/module/project/lang/de.php b/module/project/lang/de.php index f9a6cf60a2..deab788c45 100644 --- a/module/project/lang/de.php +++ b/module/project/lang/de.php @@ -65,7 +65,7 @@ $lang->project->budgetGe0 = '『Budget』must be greater than or equal $lang->project->allProjects = 'All Projects'; /* Fields. */ -$lang->project->common = 'Program'; +$lang->project->common = 'Project'; $lang->project->id = 'ID'; $lang->project->project = 'Project'; $lang->project->stage = 'Stage'; @@ -195,6 +195,7 @@ $lang->project->createExecution = "There is no {$lang->executionCommon} u $lang->project->unlinkExecutionMember = "The user participated in %s executions such as %s%s. Do you want to remove the user from those executions as well? (The data related to this user will not be deleted.)"; $lang->project->unlinkExecutionMembers = "The team members you are removing are also in the execution team of this project. Do you want to remove them from the execution team too?"; $lang->project->productTip = 'After clicking New Product, the project will not be linked to the selected product.'; +$lang->project->noDevStage = 'There is no R&D stage under this project, or you do not have access permissions. The creation of builds is not supported at the moment.'; $lang->project->tenThousand = ''; $lang->project->hundredMillion = 'Hundred Million'; @@ -307,21 +308,23 @@ $lang->project->programTitle['0'] = 'Hide'; $lang->project->programTitle['base'] = 'Base-level project only'; $lang->project->programTitle['end'] = 'End-level project only'; -$lang->project->accessDenied = 'Access denied!'; -$lang->project->chooseProgramType = 'Select the project management model'; -$lang->project->cannotCreateChild = 'It is not empty, so you cannot add a child. You can add a parent for it, and then create a child.'; -$lang->project->hasChildren = 'This project has a child project, so it cannot be deleted.'; -$lang->project->confirmDelete = "Do you want to delete [%s]?"; -$lang->project->cannotChangeToCat = "It is not empty, so you cannot change it to a parent."; -$lang->project->cannotCancelCat = "It has child projects, so you cannot unmark the parent."; -$lang->project->parentBeginEnd = "Parent begin&end date: %s ~ %s"; -$lang->project->parentBudget = "The budget of the parent project: "; -$lang->project->beginLetterParent = "The begin date of the parent project: %s. It cannot be < the begin date of its parent project."; -$lang->project->endGreaterParent = "The end date of the parent project: %s. It cannot be > the end date of its parent project."; -$lang->project->beginGreateChild = 'The start date of the project "%s" should be ≥ the start date of program "%s": %s.'; -$lang->project->endLetterChild = 'The finish date of the project "%s" should be ≤ the finish date of program "%s": %s.'; -$lang->project->childLongTime = "If a child as long-term projects, the parent should be long-term too."; -$lang->project->confirmUnlinkMember = "Do you want to remove this user from project?"; +$lang->project->accessDenied = 'Access denied!'; +$lang->project->chooseProgramType = 'Select the project management model'; +$lang->project->cannotCreateChild = 'It is not empty, so you cannot add a child. You can add a parent for it, and then create a child.'; +$lang->project->hasChildren = 'This project has a child project, so it cannot be deleted.'; +$lang->project->confirmDelete = "Do you want to delete [%s]?"; +$lang->project->cannotChangeToCat = "It is not empty, so you cannot change it to a parent."; +$lang->project->cannotCancelCat = "It has child projects, so you cannot unmark the parent."; +$lang->project->parentBeginEnd = "Parent begin&end date: %s ~ %s"; +$lang->project->parentBudget = "The budget of the parent project: "; +$lang->project->beginLetterParent = "The begin date of the parent project: %s. It cannot be < the begin date of its parent project."; +$lang->project->endGreaterParent = "The end date of the parent project: %s. It cannot be > the end date of its parent project."; +$lang->project->beginGreateChild = 'The start date of the project should be ≥ the start date of program: %s.'; +$lang->project->endLetterChild = 'The finish date of the project should be ≤ the finish date of program: %s.'; +$lang->project->begigLetterExecution = 'The start date of project should be ≤ the minimum start date of the execution: %s.'; +$lang->project->endGreateExecution = 'The finish date of the project should be ≥ the maximum finish date of the execution: %s.'; +$lang->project->childLongTime = "If a child as long-term projects, the parent should be long-term too."; +$lang->project->confirmUnlinkMember = "Do you want to remove this user from project?"; $lang->project->action = new stdclass(); $lang->project->action->managed = '$date, managed by $actor. $extra' . "\n"; diff --git a/module/project/lang/en.php b/module/project/lang/en.php index 3e07049109..6330f8cc9a 100644 --- a/module/project/lang/en.php +++ b/module/project/lang/en.php @@ -195,6 +195,7 @@ $lang->project->createExecution = "There is no {$lang->executionCommon} u $lang->project->unlinkExecutionMember = "The user participated in %s executions such as %s%s. Do you want to remove the user from those executions as well? (The data related to this user will not be deleted.)"; $lang->project->unlinkExecutionMembers = "The team members you are removing are also in the execution team of this project. Do you want to remove them from the execution team too?"; $lang->project->productTip = 'After clicking New Product, the project will not be linked to the selected product.'; +$lang->project->noDevStage = 'There is no R&D stage under this project, or you do not have access permissions. The creation of builds is not supported at the moment.'; $lang->project->tenThousand = 'Ten Thousand'; $lang->project->hundredMillion = 'Hundred Million'; @@ -318,8 +319,10 @@ $lang->project->parentBeginEnd = "The begin and end date of the parent proj $lang->project->parentBudget = "The budget of the parent project: "; $lang->project->beginLetterParent = "The begin date of the parent project: %s. It cannot be < the begin date of its parent project."; $lang->project->endGreaterParent = "The end date of the parent project: %s. It cannot be > the end date of its parent project."; -$lang->project->beginGreateChild = 'The start date of the project "%s" should be ≥ the start date of program "%s": %s.'; -$lang->project->endLetterChild = 'The finish date of the project "%s" should be ≤ the finish date of program "%s": %s.'; +$lang->project->beginGreateChild = 'The start date of the project should be ≥ the start date of program: %s.'; +$lang->project->endLetterChild = 'The finish date of the project should be ≤ the finish date of program: %s.'; +$lang->project->begigLetterExecution = 'The start date of project should be ≤ the minimum start date of the execution: %s.'; +$lang->project->endGreateExecution = 'The finish date of the project should be ≥ the maximum finish date of the execution: %s.'; $lang->project->childLongTime = "There are long-term projects in the child project, and the parent project should also be a long-term project."; $lang->project->confirmUnlinkMember = "Do you want to remove this user from project?"; diff --git a/module/project/lang/fr.php b/module/project/lang/fr.php index f3969c0654..1be54e768a 100644 --- a/module/project/lang/fr.php +++ b/module/project/lang/fr.php @@ -65,7 +65,7 @@ $lang->project->budgetGe0 = '『Budget』must be greater than or equal $lang->project->allProjects = 'All Projects'; /* Fields. */ -$lang->project->common = 'Project'; +$lang->project->common = 'Projets'; $lang->project->id = 'ID'; $lang->project->project = 'Project'; $lang->project->stage = 'Stage'; @@ -195,6 +195,7 @@ $lang->project->createExecution = "There is no {$lang->executionCommon} u $lang->project->unlinkExecutionMember = "The user participated in %s executions such as %s%s. Do you want to remove the user from those executions as well? (The data related to this user will not be deleted.)"; $lang->project->unlinkExecutionMembers = "The team members you are removing are also in the execution team of this project. Do you want to remove them from the execution team too?"; $lang->project->productTip = 'After clicking New Product, the project will not be linked to the selected product.'; +$lang->project->noDevStage = "Il n'y a pas de phase R&D dans ce projet, ou vous n'avez pas la permission d'accès. La version ne peut pas être créée pour le moment."; $lang->project->tenThousand = ''; $lang->project->hundredMillion = 'Hundred Million'; @@ -307,21 +308,23 @@ $lang->project->programTitle['0'] = 'Hide'; $lang->project->programTitle['base'] = 'Base-level project only'; $lang->project->programTitle['end'] = 'End-level project only'; -$lang->project->accessDenied = 'Access denied!'; -$lang->project->chooseProgramType = 'Select the project management model'; -$lang->project->cannotCreateChild = 'It is not empty, so you cannot add a child. You can add a parent for it, and then create a child.'; -$lang->project->hasChildren = 'This project has a child project, so it cannot be deleted.'; -$lang->project->confirmDelete = "Do you want to delete [%s]?"; -$lang->project->cannotChangeToCat = "It is not empty, so you cannot change it to a parent."; -$lang->project->cannotCancelCat = "It has child projects, so you cannot unmark the parent."; -$lang->project->parentBeginEnd = "Parent begin&end date: %s ~ %s"; -$lang->project->parentBudget = "The budget of the parent project: "; -$lang->project->beginLetterParent = "The begin date of the parent project: %s. It cannot be < the begin date of its parent project."; -$lang->project->endGreaterParent = "The end date of the parent project: %s. It cannot be > the end date of its parent project."; -$lang->project->beginGreateChild = 'La date de début du projets "%s" doit être ≥ à la date de début du programme "%s" : %s.'; -$lang->project->endLetterChild = 'La date de fin du projets "%s" doit être ≤ à la date de fin du programme "%s" : %s.'; -$lang->project->childLongTime = "If a child as long-term projects, the parent should be long-term too."; -$lang->project->confirmUnlinkMember = "Do you want to remove this user from project?"; +$lang->project->accessDenied = 'Access denied!'; +$lang->project->chooseProgramType = 'Select the project management model'; +$lang->project->cannotCreateChild = 'It is not empty, so you cannot add a child. You can add a parent for it, and then create a child.'; +$lang->project->hasChildren = 'This project has a child project, so it cannot be deleted.'; +$lang->project->confirmDelete = "Do you want to delete [%s]?"; +$lang->project->cannotChangeToCat = "It is not empty, so you cannot change it to a parent."; +$lang->project->cannotCancelCat = "It has child projects, so you cannot unmark the parent."; +$lang->project->parentBeginEnd = "Parent begin&end date: %s ~ %s"; +$lang->project->parentBudget = "The budget of the parent project: "; +$lang->project->beginLetterParent = "The begin date of the parent project: %s. It cannot be < the begin date of its parent project."; +$lang->project->endGreaterParent = "The end date of the parent project: %s. It cannot be > the end date of its parent project."; +$lang->project->beginGreateChild = 'La date de début du projets "%s" doit être ≥ à la date de début du programme "%s" : %s.'; +$lang->project->endLetterChild = 'La date de fin du projets doit être ≤ à la date de fin du programme: %s.'; +$lang->project->begigLetterExecution = 'La date de début du projet "%s" doit être ≤ à la date de début minimum d\'excution: %s'; +$lang->project->endGreateExecution = 'La date de fin du projet "%s" doit être ≥ à la date de fin maximale d\'exécution: %s.'; +$lang->project->childLongTime = "If a child as long-term projects, the parent should be long-term too."; +$lang->project->confirmUnlinkMember = "Do you want to remove this user from project?"; $lang->project->action = new stdclass(); $lang->project->action->managed = '$date, managed by $actor. $extra' . "\n"; diff --git a/module/project/lang/vi.php b/module/project/lang/vi.php index 9258dbb808..6b22c04e56 100644 --- a/module/project/lang/vi.php +++ b/module/project/lang/vi.php @@ -117,6 +117,7 @@ $lang->project->linkedProjectsTip = 'Linked projects are as follows'; $lang->project->multiLinkedProductsTip = 'The following products linked to this project are also linked to other projects, please unlink before proceeding.'; $lang->project->linkStoryByPlanTips = "This action will associate all {$lang->SRCommon} under the selected plan to this project"; $lang->project->createExecution = "There is no {$lang->executionCommon} under this project, please create {$lang->executionCommon} first"; +$lang->project->noDevStage = 'There is no R&D stage under this project, or you do not have access permissions. The creation of builds is not supported at the moment.'; $lang->project->tenThousand = ''; diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php index 04edb713da..2a4bc0aeb5 100644 --- a/module/project/lang/zh-cn.php +++ b/module/project/lang/zh-cn.php @@ -195,6 +195,7 @@ $lang->project->createExecution = "该项目下没有{$lang->executionCom $lang->project->unlinkExecutionMember = "该用户参与了%s%s%s个{$lang->execution->common},是否同时将其移除?(该用户所产生的数据不会受影响。)"; $lang->project->unlinkExecutionMembers = "移除的团队成员还参与了项目下的执行,是否同步从执行团队中移除?"; $lang->project->productTip = '点击新建产品后,项目将不会关联已选中的产品。'; +$lang->project->noDevStage = '该项目下没有研发类型的阶段,或者您没有权限访问,暂时不支持创建版本。'; $lang->project->tenThousand = '万'; $lang->project->hundredMillion = '亿'; @@ -310,18 +311,20 @@ $lang->project->programTitle['end'] = '只显示最后一级项目集'; $lang->project->accessDenied = '您无权访问该项目!'; $lang->project->chooseProgramType = '选择项目管理方式'; $lang->project->cannotCreateChild = '该项目已经有实际的内容,无法直接添加子项目。您可以为当前项目创建一个父项目,然后在新的父项目下面添加子项目。'; -$lang->project->hasChildren = '该项目有子项目存在,不能删除。'; -$lang->project->confirmDelete = '您确定删除项目“%s”吗?'; -$lang->project->cannotChangeToCat = "该项目已经有实际的内容,无法修改为父项目"; -$lang->project->cannotCancelCat = "该项目下已经有子项目,无法取消父项目标记"; -$lang->project->parentBeginEnd = "父项目起止时间:%s ~ %s"; -$lang->project->parentBudget = "父项目预算:"; -$lang->project->beginLetterParent = "父项目的开始日期:%s,开始日期不能小于父项目的开始日期"; -$lang->project->endGreaterParent = "父项目的完成日期:%s,完成日期不能大于父项目的完成日期"; -$lang->project->beginGreateChild = '项目“%s”的开始日期应大于等于项目集“%s”的最小开始日期:%s'; -$lang->project->endLetterChild = '项目“%s”的完成日期应小于等于项目集“%s”的最大完成日期:%s'; -$lang->project->childLongTime = "子项目中有长期项目,父项目也应该是长期项目"; -$lang->project->confirmUnlinkMember = "您确定从该项目中移除该用户吗?"; +$lang->project->hasChildren = '该项目有子项目存在,不能删除。'; +$lang->project->confirmDelete = '您确定删除项目“%s”吗?'; +$lang->project->cannotChangeToCat = "该项目已经有实际的内容,无法修改为父项目"; +$lang->project->cannotCancelCat = "该项目下已经有子项目,无法取消父项目标记"; +$lang->project->parentBeginEnd = "父项目起止时间:%s ~ %s"; +$lang->project->parentBudget = "父项目预算:"; +$lang->project->beginLetterParent = "父项目的开始日期:%s,开始日期不能小于父项目的开始日期"; +$lang->project->endGreaterParent = "父项目的完成日期:%s,完成日期不能大于父项目的完成日期"; +$lang->project->beginGreateChild = '项目的开始日期应大于等于项目集的最小开始日期:%s'; +$lang->project->endLetterChild = '项目的完成日期应小于等于项目集的最大完成日期:%s'; +$lang->project->begigLetterExecution = '项目的开始日期应小于等于执行的最小开始日期:%s'; +$lang->project->endGreateExecution = '项目的完成日期应大于等于执行的最大完成日期:%s'; +$lang->project->childLongTime = "子项目中有长期项目,父项目也应该是长期项目"; +$lang->project->confirmUnlinkMember = "您确定从该项目中移除该用户吗?"; $lang->project->action = new stdclass(); $lang->project->action->managed = '$date, 由 $actor 维护。$extra' . "\n"; diff --git a/module/project/lang/zh-tw.php b/module/project/lang/zh-tw.php index da49a6d435..a99512886a 100644 --- a/module/project/lang/zh-tw.php +++ b/module/project/lang/zh-tw.php @@ -179,6 +179,7 @@ $lang->project->linkStoryByPlanTips = "此操作會將所選計划下面的{$ $lang->project->createExecution = "該項目下沒有{$lang->executionCommon},請先創建{$lang->executionCommon}"; $lang->project->unlinkExecutionMember = "該用戶參與了%s%s%s個{$lang->execution->common},是否同時將其移除?(該用戶所產生的數據不會受影響。)"; $lang->project->unlinkExecutionMembers = "移除的團隊成員還參與了項目下的執行,是否同步從執行團隊中移除?"; +$lang->project->noDevStage = '該項目下沒有研發類型的階段,或者您沒有權限訪問,暫時不支持創建版本。'; $lang->project->tenThousand = '萬'; diff --git a/module/project/model.php b/module/project/model.php index 7fc4a0f36e..03147d7e1a 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -693,10 +693,11 @@ class projectModel extends model * @param bool $isQueryAll * @param string $orderBy * @param string $excludedModel + * @param string $model * @access public * @return object */ - public function getPairsByProgram($programID = '', $status = 'all', $isQueryAll = false, $orderBy = 'order_asc', $excludedModel = '') + public function getPairsByProgram($programID = '', $status = 'all', $isQueryAll = false, $orderBy = 'order_asc', $excludedModel = '', $model = '') { if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getProjectPairs(); return $this->dao->select('id, name')->from(TABLE_PROJECT) @@ -706,6 +707,7 @@ class projectModel extends model ->beginIF($programID !== '')->andWhere('parent')->eq($programID)->fi() ->beginIF($status != 'all' and $status != 'noclosed')->andWhere('status')->eq($status)->fi() ->beginIF($excludedModel)->andWhere('model')->ne($excludedModel)->fi() + ->beginIF($model)->andWhere('model')->eq($model)->fi() ->beginIF($status == 'noclosed')->andWhere('status')->ne('closed')->fi() ->beginIF(!$this->app->user->admin and !$isQueryAll)->andWhere('id')->in($this->app->user->view->projects)->fi() ->orderBy($orderBy) @@ -1094,10 +1096,10 @@ class projectModel extends model if($program) { /* Child project begin cannot less than parent. */ - if(!empty($project->name) and $project->begin < $program->begin) dao::$errors['begin'] = sprintf($this->lang->project->beginGreateChild, $project->name, $program->name, $program->begin); + if(!empty($project->name) and $project->begin < $program->begin) dao::$errors['begin'] = sprintf($this->lang->project->beginGreateChild, $program->begin); /* When parent set end then child project end cannot greater than parent. */ - if(!empty($project->name) and $$program->end != '0000-00-00' and $project->end > $program->end) dao::$errors['end'] = sprintf($this->lang->project->endLetterChild, $project->name, $program->name, $program->end); + if(!empty($project->name) and $program->end != '0000-00-00' and $project->end > $program->end) dao::$errors['end'] = sprintf($this->lang->project->endLetterChild, $program->end); if(dao::isError()) return false; } @@ -1358,10 +1360,10 @@ class projectModel extends model if($program) { /* Child project begin cannot less than parent. */ - if(!empty($project->name) and $project->begin < $program->begin) dao::$errors['begin'] = sprintf($this->lang->project->beginGreateChild, $project->name, $program->name, $program->begin); + if(!empty($project->name) and $project->begin < $program->begin) dao::$errors['begin'] = sprintf($this->lang->project->beginGreateChild, $program->begin); /* When parent set end then child project end cannot greater than parent. */ - if(!empty($project->name) and $program->end != '0000-00-00' and $project->end > $program->end) dao::$errors['end'] = sprintf($this->lang->project->endLetterChild, $project->name, $program->name, $program->end); + if(!empty($project->name) and $program->end != '0000-00-00' and $project->end > $program->end) dao::$errors['end'] = sprintf($this->lang->project->endLetterChild, $program->end); if(dao::isError()) return false; } @@ -1375,6 +1377,19 @@ class projectModel extends model } } + $executionsCount = $this->dao->select('COUNT(*) as count')->from(TABLE_PROJECT) + ->where('project')->eq($project->id) + ->andWhere('deleted')->eq('0') + ->fetchAll(); + if(!empty($executionsCount)) + { + $minExecutionBegin = $this->dao->select('begin as minBegin')->from(TABLE_PROJECT)->where('project')->eq($project->id)->andWhere('deleted')->eq('0')->orderBy('begin_asc')->fetch(); + $maxExecutionEnd = $this->dao->select('end as maxEnd')->from(TABLE_PROJECT)->where('project')->eq($project->id)->andWhere('deleted')->eq('0')->orderBy('end_desc')->fetch(); + if($minExecutionBegin and $project->begin > $minExecutionBegin->minBegin) dao::$errors['begin'] = sprintf($this->lang->project->begigLetterExecution, $minExecutionBegin->minBegin); + if($maxExecutionEnd and $project->end < $maxExecutionEnd->maxEnd) dao::$errors['end'] = sprintf($this->lang->project->endGreateExecution, $maxExecutionEnd->maxEnd); + if(dao::isError()) return false; + } + /* Judge products not empty. */ $linkedProductsCount = 0; foreach($_POST['products'] as $product) @@ -1529,14 +1544,14 @@ class projectModel extends model /* Child project begin cannot less than parent. */ if(!empty($projects[$projectID]->name) and $projects[$projectID]->begin < $parentProject->begin) { - dao::$errors['begin'] = sprintf($this->lang->project->beginGreateChild, $projects[$projectID]->name, $parentProject->name, $parentProject->begin); + dao::$errors['begin'] = sprintf($this->lang->project->beginGreateChild, $parentProject->begin); return false; } /* When parent set end then child project end cannot greater than parent. */ if(!empty($projects[$projectID]->name) and $parentProject->end != '0000-00-00' and $projects[$projectID]->end > $parentProject->end) { - dao::$errors['end'] = sprintf($this->lang->project->endLetterChild, $projects[$projectID]->name, $parentProject->name, $parentProject->end); + dao::$errors['end'] = sprintf($this->lang->project->endLetterChild, $parentProject->end); return false; } } @@ -2597,6 +2612,9 @@ class projectModel extends model if(isset($project->model) and $project->model == 'waterfall') { global $lang; + $lang->project->createExecution = str_replace($this->lang->executionCommon, $lang->project->stage, $lang->project->createExecution); + $lang->project->lastIteration = str_replace($this->lang->executionCommon, $lang->project->stage, $lang->project->lastIteration); + $this->loadModel('execution'); $lang->executionCommon = $lang->project->stage; diff --git a/module/project/view/browsebylist.html.php b/module/project/view/browsebylist.html.php index aaf684b538..5991184811 100644 --- a/module/project/view/browsebylist.html.php +++ b/module/project/view/browsebylist.html.php @@ -73,10 +73,12 @@

project->empty;?> - - ' . $lang->project->create, '', 'class="btn btn-info" data-toggle="modal"');?> - - ' . $lang->execution->create, '', 'class="btn btn-info"');?> + + + ' . $lang->project->create, '', 'class="btn btn-info" data-toggle="modal"');?> + + ' . $lang->execution->create, '', 'class="btn btn-info"');?> +

diff --git a/module/project/view/build.html.php b/module/project/view/build.html.php index 69dcb7be6e..fd803187a7 100644 --- a/module/project/view/build.html.php +++ b/module/project/view/build.html.php @@ -11,8 +11,10 @@ */ ?> + +project->noDevStage)?> project->createExecution)?> build->confirmDelete)?>
custom->key;?>
doclib->control;?> - doc->aclList, $doc->acl, "onchange='toggleAcl(this.value, \"doc\")'")?> - doc->noticeAcl['doc'][$doc->acl];?> + acl == 'private' ? 'private' : $doc->acl;?> + doc->aclList, $acl, "onchange='toggleAcl(this.value, \"doc\")'")?> + doc->noticeAcl['doc'][$acl];?>
testcase->typeList, $case->type);?> openedBy);?> lastRunner);?>lastRunDate)) echo date(DT_MONTHTIME1, strtotime($case->lastRunDate));?>lastRunDate)) echo substr($case->lastRunDate, 5, 11);?> lastRunResult) echo $lang->testcase->resultList[$case->lastRunResult];?> id", $task, 'list', 'link'); if(common::hasPriv('execution', 'testreport')) { - echo html::a($this->createLink('execution', 'testreport', "executionID=$executionID&objctType=execution&extra=$task->id"), '', '', 'class="btn " title="' . $lang->testreport->browse . '" data-app="execution"'); + echo html::a($this->createLink('execution', 'testreport', "executionID=$executionID&objctType=execution&extra=$task->id"), '', '', 'class="btn " title="' . $lang->testreport->browse . '" data-app="execution"'); } common::printIcon('testtask', 'edit', "taskID=$task->id", $task, 'list'); common::printIcon('testtask', 'delete', "taskID=$task->id", $task, 'list', 'trash', 'hiddenwin'); diff --git a/module/execution/view/treetask.html.php b/module/execution/view/treetask.html.php index 93ad75b280..388aa093bf 100644 --- a/module/execution/view/treetask.html.php +++ b/module/execution/view/treetask.html.php @@ -3,7 +3,7 @@

id?> status}";?>">processStatus('task', $task);?> - + parent > 0) echo '' . $this->lang->task->childrenAB . '';?> team)) echo '' . $this->lang->task->multipleAB . '';?> parentName) ? $task->parentName . '/' : '';?>name;?> diff --git a/module/file/control.php b/module/file/control.php index 442cf467f8..79f09b08eb 100644 --- a/module/file/control.php +++ b/module/file/control.php @@ -293,14 +293,17 @@ class file extends control * @param array $files * @param string $fieldset * @param object $object + * @param string $method * @access public * @return void */ - public function printFiles($files, $fieldset, $object = null) + public function printFiles($files, $fieldset, $object = null, $method = 'view') { $this->view->files = $files; $this->view->fieldset = $fieldset; $this->view->object = $object; + + if($method == 'view') return $this->display('file', 'viewfiles'); $this->display(); } diff --git a/module/file/lang/de.php b/module/file/lang/de.php index cee6b10663..6935145f6b 100644 --- a/module/file/lang/de.php +++ b/module/file/lang/de.php @@ -36,6 +36,7 @@ $lang->file->addFile = 'Hinzufügen'; $lang->file->beginUpload = 'Upload'; $lang->file->uploadSuccess = 'Hochgeladen!'; $lang->file->batchExport = 'Export in batches'; +$lang->file->downloadFile = 'Download'; $lang->file->pathname = 'Pfadname'; $lang->file->title = 'Titel'; diff --git a/module/file/lang/en.php b/module/file/lang/en.php index a4f66e307c..e1cd7b4114 100644 --- a/module/file/lang/en.php +++ b/module/file/lang/en.php @@ -36,6 +36,7 @@ $lang->file->addFile = 'Add'; $lang->file->beginUpload = 'Click to Upload'; $lang->file->uploadSuccess = 'Uploaded!'; $lang->file->batchExport = 'Export in batches'; +$lang->file->downloadFile = 'Download'; $lang->file->pathname = 'Path Name'; $lang->file->title = 'Title'; diff --git a/module/file/lang/fr.php b/module/file/lang/fr.php index 2d959715d0..9389a7b93c 100644 --- a/module/file/lang/fr.php +++ b/module/file/lang/fr.php @@ -36,6 +36,7 @@ $lang->file->addFile = 'Ajouter'; $lang->file->beginUpload = 'Clic pour Charger'; $lang->file->uploadSuccess = 'Chargé !'; $lang->file->batchExport = 'Export in batches'; +$lang->file->downloadFile = 'Download'; $lang->file->pathname = 'Nom Chemin'; $lang->file->title = 'Titre'; diff --git a/module/file/lang/zh-cn.php b/module/file/lang/zh-cn.php index f40ee47be0..83351d0919 100644 --- a/module/file/lang/zh-cn.php +++ b/module/file/lang/zh-cn.php @@ -36,6 +36,7 @@ $lang->file->addFile = '添加文件'; $lang->file->beginUpload = '开始上传'; $lang->file->uploadSuccess = '上传成功'; $lang->file->batchExport = '分批导出'; +$lang->file->downloadFile = '下载'; $lang->file->pathname = '路径'; $lang->file->title = '标题'; diff --git a/module/file/view/printfiles.html.php b/module/file/view/printfiles.html.php index ff83b89509..e66cbc43c8 100644 --- a/module/file/view/printfiles.html.php +++ b/module/file/view/printfiles.html.php @@ -2,7 +2,6 @@
-
file->common;?>
+ +
    + file->uploadDate . substr($file->addedDate, 0, 10); + $fileTitle = "  " . $file->title; + if(strpos($file->title, ".{$file->extension}") === false && $file->extension != 'txt') $fileTitle .= ".{$file->extension}"; + $imageWidth = 0; + if(stripos('jpg|jpeg|gif|png|bmp', $file->extension) !== false) + { + $imageSize = $this->file->getImageSize($file); + $imageWidth = $imageSize ? $imageSize[0] : 0; + } + + $fileSize = 0; + /* Show size info. */ + if($file->size < 1024) + { + $fileSize = $file->size . 'B'; + } + elseif($file->size < 1024 * 1024) + { + $file->size = round($file->size / 1024, 2); + $fileSize = $file->size . 'K'; + } + elseif($file->size < 1024 * 1024 * 1024) + { + $file->size = round($file->size / (1024 * 1024), 2); + $fileSize = $file->size . 'M'; + } + else + { + $file->size = round($file->size / (1024 * 1024 * 1024), 2); + $fileSize = $file->size . 'G'; + } + + $downloadLink = $this->createLink('file', 'download', "fileID=$file->id"); + $downloadLink .= strpos($downloadLink, '?') === false ? '?' : '&'; + $downloadLink .= $sessionString; + echo "
  • " . html::a($downloadLink, $fileTitle . " ({$fileSize})", '_blank', "onclick=\"return downloadFile($file->id, '$file->extension', $imageWidth, '$file->title')\""); + + $objectType = zget($this->config->file->objectType, $file->objectType); + if(common::hasPriv($objectType, 'edit', $object)) + { + echo "  "; + + /* Determines whether the file supports preview. */ + if($file->extension == 'txt') + { + $extension = 'txt'; + if(($postion = strrpos($file->title, '.')) !== false) $extension = substr($file->title, $postion + 1); + if($extension != 'txt') $mode = 'down'; + $file->extension = $extension; + } + + /* For the open source version of the file judgment. */ + if(stripos('txt|jpg|jpeg|gif|png|bmp', $file->extension) !== false) + { + echo html::a($downloadLink, $lang->file->preview, '_blank', "class='text-primary' onclick=\"return downloadFile($file->id, '$file->extension', $imageWidth, '$file->title')\""); + } + + /* For the max version of the file judgment. */ + if(isset($this->config->file->libreOfficeTurnon) and $this->config->file->libreOfficeTurnon == 1) + { + $officeTypes = 'doc|docx|xls|xlsx|ppt|pptx|pdf'; + if(stripos($officeTypes, $file->extension) !== false) + { + echo html::a($downloadLink, $lang->file->preview, '_blank', "class='text-primary' onclick=\"return downloadFile($file->id, '$file->extension', $imageWidth, '$file->title')\""); + } + } + + common::printLink('file', 'download', "fileID=$file->id", $lang->file->downloadFile, '_blank', "class='text-primary' title='{$lang->file->downloadFile}'"); + common::printLink('file', 'edit', "fileID=$file->id", $lang->file->edit, '', "data-width='400' class='edit iframe text-primary' title='{$lang->file->edit}'"); + if(common::hasPriv('file', 'delete')) echo html::a('###', $lang->delete, '', "class='text-primary' onclick='deleteFile($file->id)' title='$lang->delete'"); + echo ''; + } + echo '
  • '; + } + } + ?> +
+ +
+
+ + diff --git a/module/gitlab/config.php b/module/gitlab/config.php index 7fd742944a..ac86fa3db8 100644 --- a/module/gitlab/config.php +++ b/module/gitlab/config.php @@ -124,3 +124,7 @@ $config->gitlab->accessLevel['owner'] = 50; /* Minimum compatible version. */ $config->gitlab->minCompatibleVersion = '9.0'; + +$config->gitlab->menus['project'] = 'browseProject'; +$config->gitlab->menus['group'] = 'browseGroup'; +$config->gitlab->menus['user'] = 'browseUser'; diff --git a/module/gitlab/control.php b/module/gitlab/control.php index 942567f049..564f183c93 100644 --- a/module/gitlab/control.php +++ b/module/gitlab/control.php @@ -325,8 +325,9 @@ class gitlab extends control if(!$openID) return print(js::alert($this->lang->gitlab->mustBindUser) . js::locate($this->createLink('gitlab', 'browse'))); } - $groups = $this->gitlab->apiGetGroups($gitlabID, $orderBy); - $adminGroups = $this->gitlab->apiGetGroups($gitlabID, $orderBy, 'owner'); + $keyword = fixer::input('post')->setDefault('keyword', '')->get('keyword'); + $groups = $this->gitlab->apiGetGroups($gitlabID, $orderBy, '', $keyword); + $adminGroups = $this->gitlab->apiGetGroups($gitlabID, $orderBy, 'owner', $keyword); $adminGroupIDList = array(); foreach($adminGroups as $group) $adminGroupIDList[] = $group->id; @@ -337,6 +338,7 @@ class gitlab extends control $this->view->gitlabGroupList = $groups; $this->view->adminGroupIDList = $adminGroupIDList; $this->view->orderBy = $orderBy; + $this->view->keyword = $keyword; $this->display(); } @@ -558,11 +560,22 @@ class gitlab extends control if(!$user->is_admin) $isAdmin = false; } + $keyword = fixer::input('post')->setDefault('keyword', '')->get('keyword'); + $users = $this->gitlab->apiGetUsers($gitlabID, false, $orderBy); + if($keyword) + { + foreach($users as $key => $user) + { + if(strpos($user->realname, $keyword) === false) unset($users[$key]); + } + } + $this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->browseUser; $this->view->gitlabID = $gitlabID; - $this->view->gitlabUserList = $this->gitlab->apiGetUsers($gitlabID, false, $orderBy); + $this->view->gitlabUserList = $users; $this->view->orderBy = $orderBy; $this->view->isAdmin = $isAdmin; + $this->view->keyword = $keyword; $this->display(); } @@ -583,10 +596,22 @@ class gitlab extends control return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseUser', "gitlabID=$gitlabID"))); } - $userPairs = $this->loadModel('user')->getPairs('noclosed|noletter'); + $users = $this->loadModel('user')->getList(); + $bindedUsers = $this->gitlab->getUserAccountIdPairs($gitlabID); + $userPairs = array('' => ''); + $userInfos = array(); + foreach($users as $key => $user) + { + if(!isset($bindedUsers[$user->account])) + { + $userPairs[$user->account] = $user->realname; + $userInfos[$user->account] = $user; + } + } $this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->user->create; $this->view->userPairs = $userPairs; + $this->view->users = $userInfos; $this->view->gitlabID = $gitlabID; $this->display(); } @@ -689,7 +714,10 @@ class gitlab extends control $project->isMaintainer = $this->gitlab->checkUserAccess($gitlabID, $project->id, $project, $groupIDList, 'maintainer'); } - $gitlab = $this->gitlab->getByID($gitlabID); + $gitlab = $this->gitlab->getByID($gitlabID); + $repos = $this->loadModel('repo')->getGitLabRepoList($gitlabID); + $repoPairs = array(); + foreach($repos as $repo) $repoPairs[$repo->path] = $repo->id; $this->view->gitlab = $gitlab; $this->view->keyword = urldecode(urldecode($keyword)); @@ -698,6 +726,7 @@ class gitlab extends control $this->view->gitlabID = $gitlabID; $this->view->gitlabProjectList = $result['projects']; $this->view->orderBy = $orderBy; + $this->view->repoPairs = $repoPairs; $this->display(); } diff --git a/module/gitlab/js/browseproject.js b/module/gitlab/js/browseproject.js deleted file mode 100644 index af5f37901a..0000000000 --- a/module/gitlab/js/browseproject.js +++ /dev/null @@ -1,17 +0,0 @@ -$(document).ready(function() -{ - $('#projectSearch').click(function() - { - triggerSearch(); - }); - $('#keyword').keypress(function(event) - { - if(event.which == 13) triggerSearch(); - }) - -}); - -function triggerSearch() -{ - $("#gitlabprojectForm").submit(); -} diff --git a/module/gitlab/js/common.js b/module/gitlab/js/common.js index d4c0d829bb..b339bcab90 100644 --- a/module/gitlab/js/common.js +++ b/module/gitlab/js/common.js @@ -17,4 +17,22 @@ function setAvatar() $(".avatar img").attr("src", window.URL.createObjectURL(files[0])); $(".avatar").removeClass('hidden'); }); -} \ No newline at end of file +} + +$(document).ready(function() +{ + $('#gitlabSearch').click(function() + { + triggerSearch(); + }); + $('#keyword').keypress(function(event) + { + if(event.which == 13) triggerSearch(); + }) + +}); + +function triggerSearch() +{ + $("#gitlabForm").submit(); +} diff --git a/module/gitlab/js/createuser.js b/module/gitlab/js/createuser.js index b7407093da..6ca0c4809d 100644 --- a/module/gitlab/js/createuser.js +++ b/module/gitlab/js/createuser.js @@ -1,4 +1,20 @@ $(document).ready(function() { setAvatar(); -}); \ No newline at end of file + $('#account').change(function() + { + var account = $(this).val(); + var user = users[account]; + var name = ''; + var email = ''; + if(account && user) + { + name = user.realname; + account = user.account; + email = user.email; + } + $('#name').val(name); + $('#username').val(account); + $('#email').val(email); + }) +}); diff --git a/module/gitlab/js/managegroupmembers.js b/module/gitlab/js/managegroupmembers.js index a9391db43b..48aaa55e1b 100644 --- a/module/gitlab/js/managegroupmembers.js +++ b/module/gitlab/js/managegroupmembers.js @@ -41,6 +41,7 @@ function addItem(obj) */ function deleteItem(obj) { + if($(obj).hasClass('disabled')) return false; if($('#teamForm .table-form tbody').children().length < 2) return false; $(obj).closest('tr').remove(); } diff --git a/module/gitlab/lang/de.php b/module/gitlab/lang/de.php index 9df7073538..169875c665 100644 --- a/module/gitlab/lang/de.php +++ b/module/gitlab/lang/de.php @@ -24,14 +24,14 @@ $lang->gitlab->lastUpdate = 'Last Update'; $lang->gitlab->confirmAddWebhook = 'Are you sure about creating Webhook?'; $lang->gitlab->addWebhookSuccess = 'Webhook created successfully'; $lang->gitlab->failCreateWebhook = 'Failed to create Webhook, please view the log'; -$lang->gitlab->placeholderSearch = 'Project name'; +$lang->gitlab->placeholderSearch = 'Enter name'; $lang->gitlab->browseAction = 'GitLab List'; $lang->gitlab->deleteAction = 'Delete GitLab'; $lang->gitlab->gitlabProject = "GitLab Project"; -$lang->gitlab->browseProject = "GitLab Project List"; -$lang->gitlab->browseUser = "User List"; -$lang->gitlab->browseGroup = "Group List"; +$lang->gitlab->browseProject = "Project"; +$lang->gitlab->browseUser = "User"; +$lang->gitlab->browseGroup = "Group"; $lang->gitlab->browseBranch = "GitLab Branch List"; $lang->gitlab->browseTag = "GitLab Tag List"; $lang->gitlab->browseTagPriv = "GitLab Tag protected List"; @@ -62,12 +62,13 @@ $lang->gitlab->editTagPriv = 'Edit tag protected'; $lang->gitlab->deleteTagPriv = 'Delete tag protected'; $lang->gitlab->id = 'ID'; -$lang->gitlab->name = "GitLab Server"; +$lang->gitlab->name = "Server Name"; $lang->gitlab->url = 'Server URL'; $lang->gitlab->token = 'Token'; $lang->gitlab->defaultProject = 'Default Project'; $lang->gitlab->private = 'MD5 Verify'; +$lang->gitlab->server = "Server List"; $lang->gitlab->lblCreate = 'Create GitLab Server'; $lang->gitlab->desc = 'Description'; $lang->gitlab->tokenFirst = 'When the Token is not empty, the Token will be used first'; diff --git a/module/gitlab/lang/en.php b/module/gitlab/lang/en.php index 9df7073538..169875c665 100644 --- a/module/gitlab/lang/en.php +++ b/module/gitlab/lang/en.php @@ -24,14 +24,14 @@ $lang->gitlab->lastUpdate = 'Last Update'; $lang->gitlab->confirmAddWebhook = 'Are you sure about creating Webhook?'; $lang->gitlab->addWebhookSuccess = 'Webhook created successfully'; $lang->gitlab->failCreateWebhook = 'Failed to create Webhook, please view the log'; -$lang->gitlab->placeholderSearch = 'Project name'; +$lang->gitlab->placeholderSearch = 'Enter name'; $lang->gitlab->browseAction = 'GitLab List'; $lang->gitlab->deleteAction = 'Delete GitLab'; $lang->gitlab->gitlabProject = "GitLab Project"; -$lang->gitlab->browseProject = "GitLab Project List"; -$lang->gitlab->browseUser = "User List"; -$lang->gitlab->browseGroup = "Group List"; +$lang->gitlab->browseProject = "Project"; +$lang->gitlab->browseUser = "User"; +$lang->gitlab->browseGroup = "Group"; $lang->gitlab->browseBranch = "GitLab Branch List"; $lang->gitlab->browseTag = "GitLab Tag List"; $lang->gitlab->browseTagPriv = "GitLab Tag protected List"; @@ -62,12 +62,13 @@ $lang->gitlab->editTagPriv = 'Edit tag protected'; $lang->gitlab->deleteTagPriv = 'Delete tag protected'; $lang->gitlab->id = 'ID'; -$lang->gitlab->name = "GitLab Server"; +$lang->gitlab->name = "Server Name"; $lang->gitlab->url = 'Server URL'; $lang->gitlab->token = 'Token'; $lang->gitlab->defaultProject = 'Default Project'; $lang->gitlab->private = 'MD5 Verify'; +$lang->gitlab->server = "Server List"; $lang->gitlab->lblCreate = 'Create GitLab Server'; $lang->gitlab->desc = 'Description'; $lang->gitlab->tokenFirst = 'When the Token is not empty, the Token will be used first'; diff --git a/module/gitlab/lang/fr.php b/module/gitlab/lang/fr.php index 9df7073538..169875c665 100644 --- a/module/gitlab/lang/fr.php +++ b/module/gitlab/lang/fr.php @@ -24,14 +24,14 @@ $lang->gitlab->lastUpdate = 'Last Update'; $lang->gitlab->confirmAddWebhook = 'Are you sure about creating Webhook?'; $lang->gitlab->addWebhookSuccess = 'Webhook created successfully'; $lang->gitlab->failCreateWebhook = 'Failed to create Webhook, please view the log'; -$lang->gitlab->placeholderSearch = 'Project name'; +$lang->gitlab->placeholderSearch = 'Enter name'; $lang->gitlab->browseAction = 'GitLab List'; $lang->gitlab->deleteAction = 'Delete GitLab'; $lang->gitlab->gitlabProject = "GitLab Project"; -$lang->gitlab->browseProject = "GitLab Project List"; -$lang->gitlab->browseUser = "User List"; -$lang->gitlab->browseGroup = "Group List"; +$lang->gitlab->browseProject = "Project"; +$lang->gitlab->browseUser = "User"; +$lang->gitlab->browseGroup = "Group"; $lang->gitlab->browseBranch = "GitLab Branch List"; $lang->gitlab->browseTag = "GitLab Tag List"; $lang->gitlab->browseTagPriv = "GitLab Tag protected List"; @@ -62,12 +62,13 @@ $lang->gitlab->editTagPriv = 'Edit tag protected'; $lang->gitlab->deleteTagPriv = 'Delete tag protected'; $lang->gitlab->id = 'ID'; -$lang->gitlab->name = "GitLab Server"; +$lang->gitlab->name = "Server Name"; $lang->gitlab->url = 'Server URL'; $lang->gitlab->token = 'Token'; $lang->gitlab->defaultProject = 'Default Project'; $lang->gitlab->private = 'MD5 Verify'; +$lang->gitlab->server = "Server List"; $lang->gitlab->lblCreate = 'Create GitLab Server'; $lang->gitlab->desc = 'Description'; $lang->gitlab->tokenFirst = 'When the Token is not empty, the Token will be used first'; diff --git a/module/gitlab/lang/vi.php b/module/gitlab/lang/vi.php new file mode 100644 index 0000000000..169875c665 --- /dev/null +++ b/module/gitlab/lang/vi.php @@ -0,0 +1,239 @@ +gitlab = new stdclass; +$lang->gitlab->common = 'GitLab'; +$lang->gitlab->browse = 'GitLab Browse'; +$lang->gitlab->search = 'Search'; +$lang->gitlab->create = 'Create GitLab'; +$lang->gitlab->edit = 'Edit GitLab'; +$lang->gitlab->view = 'View GitLab'; +$lang->gitlab->bindUser = 'Bind User'; +$lang->gitlab->webhook = 'Webhook'; +$lang->gitlab->bindProduct = 'Import Product'; +$lang->gitlab->importIssue = 'Import Issue'; +$lang->gitlab->delete = 'Delete GitLab'; +$lang->gitlab->confirmDelete = 'Do you want to delete this GitLab server?'; +$lang->gitlab->gitlabAccount = 'GitLab Account'; +$lang->gitlab->zentaoAccount = 'Zentao Account'; +$lang->gitlab->bindingStatus = 'Binding Status'; +$lang->gitlab->notBind = 'Not bind'; +$lang->gitlab->binded = 'Binded'; +$lang->gitlab->bindedError = 'The bound user has been deleted or modified. Please bind again.'; +$lang->gitlab->bindDynamic = '%s and Zentao user %s'; +$lang->gitlab->serverFail = 'Connect to GitLab server failed, please check the GitLab server.'; +$lang->gitlab->lastUpdate = 'Last Update'; +$lang->gitlab->confirmAddWebhook = 'Are you sure about creating Webhook?'; +$lang->gitlab->addWebhookSuccess = 'Webhook created successfully'; +$lang->gitlab->failCreateWebhook = 'Failed to create Webhook, please view the log'; +$lang->gitlab->placeholderSearch = 'Enter name'; + +$lang->gitlab->browseAction = 'GitLab List'; +$lang->gitlab->deleteAction = 'Delete GitLab'; +$lang->gitlab->gitlabProject = "GitLab Project"; +$lang->gitlab->browseProject = "Project"; +$lang->gitlab->browseUser = "User"; +$lang->gitlab->browseGroup = "Group"; +$lang->gitlab->browseBranch = "GitLab Branch List"; +$lang->gitlab->browseTag = "GitLab Tag List"; +$lang->gitlab->browseTagPriv = "GitLab Tag protected List"; +$lang->gitlab->gitlabIssue = "GitLab Issue"; +$lang->gitlab->zentaoProduct = 'Zentao Product'; +$lang->gitlab->objectType = 'Type'; // task, bug, story +$lang->gitlab->manageProjectMembers = 'Manage project member'; +$lang->gitlab->createProject = 'Create GitLab project'; +$lang->gitlab->editProject = 'Eidt GitLab project'; +$lang->gitlab->deleteProject = 'Delete GitLab project'; +$lang->gitlab->createGroup = 'Create group'; +$lang->gitlab->editGroup = 'Edit group'; +$lang->gitlab->deleteGroup = 'Delete group'; +$lang->gitlab->createUser = 'Create user'; +$lang->gitlab->editUser = 'Edit user'; +$lang->gitlab->deleteUser = 'Delete user'; +$lang->gitlab->createBranch = 'Add branch'; +$lang->gitlab->manageGroupMembers = 'Manage group member'; +$lang->gitlab->createWebhook = 'Create Webhook'; +$lang->gitlab->browseBranchPriv = 'Protect branch'; +$lang->gitlab->createBranchPriv = 'Cerate branch protected'; +$lang->gitlab->editBranchPriv = 'Edit branch protected'; +$lang->gitlab->deleteBranchPriv = 'Delete branch protected'; +$lang->gitlab->createTag = 'Create Tag'; +$lang->gitlab->deleteTag = 'Delete tag'; +$lang->gitlab->createTagPriv = 'Create tag protected'; +$lang->gitlab->editTagPriv = 'Edit tag protected'; +$lang->gitlab->deleteTagPriv = 'Delete tag protected'; + +$lang->gitlab->id = 'ID'; +$lang->gitlab->name = "Server Name"; +$lang->gitlab->url = 'Server URL'; +$lang->gitlab->token = 'Token'; +$lang->gitlab->defaultProject = 'Default Project'; +$lang->gitlab->private = 'MD5 Verify'; + +$lang->gitlab->server = "Server List"; +$lang->gitlab->lblCreate = 'Create GitLab Server'; +$lang->gitlab->desc = 'Description'; +$lang->gitlab->tokenFirst = 'When the Token is not empty, the Token will be used first'; +$lang->gitlab->tips = 'When using a password, please disable the "Prevent cross-site request forgery" option in the GitLab global security settings.'; +$lang->gitlab->emptyError = " cannot be empty"; +$lang->gitlab->createSuccess = "Create success"; +$lang->gitlab->mustBindUser = 'You have not registered the GitLab account, please contact the administrator to register.'; +$lang->gitlab->noAccess = 'Permission denied'; +$lang->gitlab->notCompatible = 'The current GitLab version is not compatible with ZenTao, please upgrade the GitLab version and try again'; +$lang->gitlab->deleted = 'Deleted'; + +$lang->gitlab->placeholder = new stdclass; +$lang->gitlab->placeholder->name = ''; +$lang->gitlab->placeholder->url = "Please fill in the access address of the GitLab Server homepage, as: https://gitlab.zentao.net."; +$lang->gitlab->placeholder->token = "Please fill in the access token of an account with root privileges."; +$lang->gitlab->placeholder->projectPath = "It should contain only letters, digits, underscore, hyphen and period. It should not start with hypen, or end with .git or .atom."; + +$lang->gitlab->noImportableIssues = "There are currently no issues available for import."; +$lang->gitlab->tokenError = "The current token is not root rights."; +$lang->gitlab->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in GitLab."; +$lang->gitlab->hostError = "So the current GitLab server address is invalid or the current GitLab version is not compatible with ZenTao, please confirm that the current server can be accessed or contact the administrator to upgrade the GitLab version to %s or above and try again."; +$lang->gitlab->bindUserError = "Can not bind users repeatedly %s"; +$lang->gitlab->importIssueError = "The execution to which this issue belongs is not selected."; +$lang->gitlab->importIssueWarn = "There is a problem of import failure, you can try to import again."; + +$lang->gitlab->accessLevels[10] = 'Guest'; +$lang->gitlab->accessLevels[20] = 'Reporter'; +$lang->gitlab->accessLevels[30] = 'Developer'; +$lang->gitlab->accessLevels[40] = 'Maintainer'; +$lang->gitlab->accessLevels[50] = 'Owner'; + +$lang->gitlab->apiError[0] = 'internal is not allowed in a private group.'; +$lang->gitlab->apiError[1] = 'public is not allowed in a private group.'; +$lang->gitlab->apiError[2] = 'is too short (minimum is 8 characters)'; +$lang->gitlab->apiError[3] = "can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'"; +$lang->gitlab->apiError[4] = 'Branch already exists'; +$lang->gitlab->apiError[5] = 'Failed to save group {:path=>["has already been taken"]}'; +$lang->gitlab->apiError[6] = '403 Forbidden'; + +$lang->gitlab->errorLang[0] = 'You cannot set Internal as its Visibility Level, if it is private in GitLab.'; +$lang->gitlab->errorLang[1] = 'You cannot set Public as its Visibility Level, if it is private in GitLab.'; +$lang->gitlab->errorLang[2] = 'Password is too short (minimum is 8 characters)'; +$lang->gitlab->errorLang[3] = 'It should contain only letters, digits, underscore, hyphen and period. It should not start with hypen, or end with .git or .atom.'; +$lang->gitlab->errorLang[4] = 'Branch already exists.'; +$lang->gitlab->errorLang[5] = 'Failed to save group, path has already been taken.'; +$lang->gitlab->errorLang[6] = $lang->gitlab->noAccess; + +$lang->gitlab->project = new stdclass; +$lang->gitlab->project->id = "Project ID"; +$lang->gitlab->project->name = "Project name"; +$lang->gitlab->project->create = "Create GitLab project"; +$lang->gitlab->project->edit = "Edit GitLab project"; +$lang->gitlab->project->url = "Project URL"; +$lang->gitlab->project->path = "Project slug"; +$lang->gitlab->project->description = "Project description"; +$lang->gitlab->project->visibility = "Visibility Level"; +$lang->gitlab->project->visibilityList['private'] = "Private(Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group)"; +$lang->gitlab->project->visibilityList['internal'] = "Internal(The project can be accessed by any logged in user except external users)"; +$lang->gitlab->project->visibilityList['public'] = "Public(The project can be accessed without any authentication)"; +$lang->gitlab->project->star = "Stars"; +$lang->gitlab->project->fork = "Forks"; +$lang->gitlab->project->mergeRequests = "Merge Requests"; +$lang->gitlab->project->issues = "Issues"; +$lang->gitlab->project->tagList = "Topics"; +$lang->gitlab->project->tagListTips = "Separate topics with commas."; +$lang->gitlab->project->emptyNameError = "Project name cannot be empty."; +$lang->gitlab->project->emptyPathError = "Project slug cannot be empty."; +$lang->gitlab->project->confirmDelete = 'Do you want to delete this GitLab project?'; +$lang->gitlab->project->notbindedError = 'GitLab user has not been bound, unable to modify permissions!'; +$lang->gitlab->project->publicTip = 'The visible status of the current project will be modified to public, and the project can be accessed without any authentication in GitLab. '; + +$lang->gitlab->user = new stdclass; +$lang->gitlab->user->id = "User ID"; +$lang->gitlab->user->name = "Name"; +$lang->gitlab->user->username = "Username"; +$lang->gitlab->user->email = "Email"; +$lang->gitlab->user->password = "Password"; +$lang->gitlab->user->passwordRepeat = "Repeat Password"; +$lang->gitlab->user->projectsLimit = "Projects limit"; +$lang->gitlab->user->canCreateGroup = "Can create group"; +$lang->gitlab->user->external = "External"; +$lang->gitlab->user->externalTip = "External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects, groups, or personal snippets."; +$lang->gitlab->user->bind = "Zentao user"; +$lang->gitlab->user->avatar = "Avatar"; +$lang->gitlab->user->skype = "Skype"; +$lang->gitlab->user->linkedin = "Linkedin"; +$lang->gitlab->user->twitter = "Twitter"; +$lang->gitlab->user->websiteUrl = "Website url"; +$lang->gitlab->user->note = "Note"; +$lang->gitlab->user->createOn = "Created on"; +$lang->gitlab->user->lastActivity = "Last activity"; +$lang->gitlab->user->create = "Create GitLab user"; +$lang->gitlab->user->edit = "Edit GitLab user"; +$lang->gitlab->user->emptyError = "cannot be empty"; +$lang->gitlab->user->passwordError = "The second password is inconsistent!"; +$lang->gitlab->user->bindError = "The user has been bound!"; +$lang->gitlab->user->confirmDelete = 'Do you want to delete this GitLab user?'; + +$lang->gitlab->group = new stdclass; +$lang->gitlab->group->id = "Group ID"; +$lang->gitlab->group->name = "Group name"; +$lang->gitlab->group->path = "Group URL"; +$lang->gitlab->group->pathTip = "Changing group URL can have unintended side effects."; +$lang->gitlab->group->description = "Group description"; +$lang->gitlab->group->avatar = "Group avatar"; +$lang->gitlab->group->avatarTip = 'Max file size is 200 KB.'; +$lang->gitlab->group->visibility = "Visibility level"; +$lang->gitlab->group->visibilityList['private'] = "Private(The group and its projects can only be viewed by members)"; +$lang->gitlab->group->visibilityList['internal'] = "Internal(The group and any internal projects can be viewed by any logged in user except external users)"; +$lang->gitlab->group->visibilityList['public'] = "Public(The group and any public projects can be viewed without any authentication.)"; +$lang->gitlab->group->permission = 'Permission'; +$lang->gitlab->group->requestAccessEnabledTip = "Allow users to request access (if visibility is public or internal)"; +$lang->gitlab->group->lfsEnabled = 'Large File Storage'; +$lang->gitlab->group->lfsEnabledTip = "Allow projects within this group to use Git LFS(This setting can be overridden in each project)"; +$lang->gitlab->group->projectCreationLevel = "Allowed to create projects"; +$lang->gitlab->group->projectCreationLevelList['noone'] = "No one"; +$lang->gitlab->group->projectCreationLevelList['maintainer'] = "Maintainers"; +$lang->gitlab->group->projectCreationLevelList['developer'] = "Developers + Maintainers"; +$lang->gitlab->group->subgroupCreationLevel = "Allowed to create projects"; +$lang->gitlab->group->subgroupCreationLevelList['owner'] = "Owners"; +$lang->gitlab->group->subgroupCreationLevelList['maintainer'] = "Maintainers"; +$lang->gitlab->group->create = "Create Group"; +$lang->gitlab->group->edit = "Edit Group"; +$lang->gitlab->group->createOn = "Created on"; +$lang->gitlab->group->members = "Group Members"; +$lang->gitlab->group->confirmDelete = 'Do you want to delete this GitLab group?'; +$lang->gitlab->group->emptyError = "cannot be empty"; +$lang->gitlab->group->manageMembers = 'Manage Group Members'; +$lang->gitlab->group->memberName = 'Account'; +$lang->gitlab->group->memberAccessLevel = 'Access Level'; +$lang->gitlab->group->memberExpiresAt = 'Expiration time'; +$lang->gitlab->group->repeatError = "Group members cannot be added repeatedly"; +$lang->gitlab->group->publicTip = 'The visible status of the current group will be modified to public, and the group can be accessed without any authentication in GitLab. '; + +$lang->gitlab->branch = new stdclass(); +$lang->gitlab->branch->name = 'Branch name'; +$lang->gitlab->branch->from = 'Create from'; +$lang->gitlab->branch->create = 'Create'; +$lang->gitlab->branch->lastCommitter = 'Last Committer'; +$lang->gitlab->branch->lastCommittedDate = 'Last Committed Date'; +$lang->gitlab->branch->accessLevel = "Branch protection list"; +$lang->gitlab->branch->mergeAllowed = "Merge Allowed"; +$lang->gitlab->branch->pushAllowed = "Push Allowed"; +$lang->gitlab->branch->placeholderSearch = "Branch name"; +$lang->gitlab->branch->placeholderSelect = "Branch name"; +$lang->gitlab->branch->confirmDelete = 'Branch will be writable for developers. Are you sure?'; +$lang->gitlab->branch->branchCreationLevelList[40] = "Maintainers"; +$lang->gitlab->branch->branchCreationLevelList[30] = "Developers + Maintainers"; +$lang->gitlab->branch->branchCreationLevelList[0] = "No one"; +$lang->gitlab->branch->emptyPrivNameError = "Branch cannot be empty."; +$lang->gitlab->branch->issetPrivNameError = "The protection branch already exists"; + +$lang->gitlab->tag = new stdclass(); +$lang->gitlab->tag->name = 'Tag name'; +$lang->gitlab->tag->ref = 'Create from'; +$lang->gitlab->tag->lastCommitter = 'Last Committer'; +$lang->gitlab->tag->lastCommittedDate = 'Last Committed Date'; +$lang->gitlab->tag->placeholderSearch = "Enter branch tag"; +$lang->gitlab->tag->message = 'Message'; +$lang->gitlab->tag->emptyNameError = "Name cannot be empty."; +$lang->gitlab->tag->emptyRefError = "Create from cannot be empty."; +$lang->gitlab->tag->issetNameError = "The tag already exists"; +$lang->gitlab->tag->confirmDelete = 'Do you want to delete this GitLab tag?'; +$lang->gitlab->tag->protected = 'Protected'; +$lang->gitlab->tag->accessLevel = 'Allow creation'; +$lang->gitlab->tag->protectConfirmDel = 'Do you want to delete this GitLab tag protected?'; +$lang->gitlab->tag->emptyPrivNameError = 'Tag cannot be empty.'; +$lang->gitlab->tag->issetPrivNameError = 'The protection tag already exists.'; diff --git a/module/gitlab/lang/zh-cn.php b/module/gitlab/lang/zh-cn.php index d3235a8c3a..d9ac66d15f 100644 --- a/module/gitlab/lang/zh-cn.php +++ b/module/gitlab/lang/zh-cn.php @@ -24,14 +24,14 @@ $lang->gitlab->lastUpdate = '最后更新'; $lang->gitlab->confirmAddWebhook = '您确定创建Webhook吗?'; $lang->gitlab->addWebhookSuccess = 'Webhook创建成功'; $lang->gitlab->failCreateWebhook = 'Webhook创建失败,请查看日志'; -$lang->gitlab->placeholderSearch = '请输入项目名称'; +$lang->gitlab->placeholderSearch = '请输入名称'; $lang->gitlab->browseAction = 'GitLab列表'; $lang->gitlab->deleteAction = '删除GitLab'; $lang->gitlab->gitlabProject = "{$lang->gitlab->common}项目"; -$lang->gitlab->browseProject = "{$lang->gitlab->common}项目列表"; -$lang->gitlab->browseUser = "用户列表"; -$lang->gitlab->browseGroup = "群组列表"; +$lang->gitlab->browseProject = "项目"; +$lang->gitlab->browseUser = "用户"; +$lang->gitlab->browseGroup = "群组"; $lang->gitlab->browseBranch = "GitLab分支列表"; $lang->gitlab->browseTag = "GitLab标签列表"; $lang->gitlab->browseTagPriv = "GitLab标签保护列表"; @@ -62,12 +62,13 @@ $lang->gitlab->editTagPriv = '编辑标签保护'; $lang->gitlab->deleteTagPriv = '删除标签保护'; $lang->gitlab->id = 'ID'; -$lang->gitlab->name = "{$lang->gitlab->common}服务器"; +$lang->gitlab->name = "服务器名称"; $lang->gitlab->url = '服务器地址'; $lang->gitlab->token = 'Token'; $lang->gitlab->defaultProject = '默认项目'; $lang->gitlab->private = 'MD5验证'; +$lang->gitlab->server = "服务器列表"; $lang->gitlab->lblCreate = '添加GitLab服务器'; $lang->gitlab->desc = '描述'; $lang->gitlab->tokenFirst = 'Token不为空时,优先使用Token。'; diff --git a/module/gitlab/model.php b/module/gitlab/model.php index 65f147a955..ee475629e2 100644 --- a/module/gitlab/model.php +++ b/module/gitlab/model.php @@ -601,10 +601,11 @@ class gitlabModel extends model * @param int $gitlabID * @param string $orderBy * @param string $minRole + * @param string $keyword * @access public * @return object */ - public function apiGetGroups($gitlabID, $orderBy = 'id_desc', $minRole = '') + public function apiGetGroups($gitlabID, $orderBy = 'id_desc', $minRole = '', $keyword = '') { $apiRoot = $this->getApiRoot($gitlabID); $url = sprintf($apiRoot, "/groups"); @@ -617,6 +618,8 @@ class gitlabModel extends model $url .= '&min_access_level=' . $this->config->gitlab->accessLevel[$minRole]; } + if($keyword) $url .= '&search=' . urlencode($keyword); + $order = 'id'; $sort = 'desc'; if(strpos($orderBy, '_') !== false) list($order, $sort) = explode('_', $orderBy); @@ -2854,4 +2857,43 @@ class gitlabModel extends model $apiRoot .= '&sudo=' . $users[0]->id; return $this->apiGet($apiRoot, '/user'); } + + /** + * Get gitlab menu. + * + * @param int $gitlabID + * @param string $type + * @access public + * @return void + */ + public function getGitlabMenu($gitlabID = 0, $type = 'project') + { + $html = '
'; + + /* Gitlab server list. */ + $gitlabs = $this->getPairs(); + $html .= "
"; + $tips = $gitlabID >0 ? zget($gitlabs, $gitlabID, $this->lang->gitlab->server) : $this->lang->gitlab->server; + $html .= html::a('javascript:;', $tips . " ", '', "data-toggle='dropdown' class='btn btn-link'"); + $html .= "
'; + + /* Other route. */ + foreach($this->config->gitlab->menus as $key => $method) + { + $lang = 'browse' . ucwords($key); + $title = $this->lang->gitlab->$lang; + $label = "$title"; + $active = $key == $type ? 'btn-active-text' : ''; + $html .= html::a(inlink($method, "gitlabID=$gitlabID"), $label, '', "id='{$key}' class='btn btn-link $active' title='$title'"); + } + + $html .= '
'; + return $html; + } } diff --git a/module/gitlab/view/browse.html.php b/module/gitlab/view/browse.html.php index 81b197a04c..af931fd6d9 100644 --- a/module/gitlab/view/browse.html.php +++ b/module/gitlab/view/browse.html.php @@ -12,6 +12,9 @@ ?>

gitlab->id);?> gitlab->name);?> gitlab->url);?>actions;?>actions;?>
- - ">name;?> + + ">name;?> name;?> @@ -52,14 +55,10 @@ url, $gitlab->url, '_target');?> isAdminToken) ? '' : 'disabled'; - $notBind = $gitlab->isBindUser ? '' : 'disabled'; - common::printLink('gitlab', 'browseProject', "gitlabID=$id", " ", '',"title='{$lang->gitlab->browseProject}' class='btn {$notBind}'"); - common::printLink('gitlab', 'browseGroup', "gitlabID=$id", " ", '', "title='{$lang->gitlab->browseGroup}' class='btn {$notBind}'"); - common::printLink('gitlab', 'edit', "gitlabID=$id", " ", '',"title='{$lang->gitlab->edit}' class='btn btn-primary'"); - common::printLink('gitlab', 'browseUser', "gitlabID=$id", " ", '', "title='{$lang->gitlab->browseUser}' class='btn {$disabled} {$notBind}' ,'disabled'"); - common::printLink('gitlab', 'bindUser', "id=$id", " ", '', "title='{$lang->gitlab->bindUser}' class='btn {$disabled} {$notBind}' ,'disabled'"); - if(common::hasPriv('gitlab', 'delete')) echo html::a($this->createLink('gitlab', 'delete', "gitlabID=$id"), '', 'hiddenwin', "title='{$lang->gitlab->delete}' class='btn'"); + $disabled = (empty($gitlab->isAdminToken) or !$gitlab->isBindUser) ? false : true; + common::printIcon('gitlab', 'edit', "gitlabID=$id", '', 'list', 'edit'); + echo common::buildIconButton('gitlab', 'bindUser', "gitlabID=$id", '', 'list', 'link', '', '', false, '', '', 0, $disabled); + common::printIcon('gitlab', 'delete', "gitlabID=$id", '', 'list', 'trash', 'hiddenwin'); ?>
created_at, 0, 10);?> user->admin or in_array($gitlabGroup->id, $adminGroupIDList)) ? '' : 'disabled'; + $isAdmin = ($app->user->admin or in_array($gitlabGroup->id, $adminGroupIDList)) ? true : false; common::printLink('gitlab', 'manageGroupMembers', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", " ", '',"title='{$lang->gitlab->group->manageMembers}' class='btn'"); - common::printLink('gitlab', 'editGroup', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", " ", '', "title='{$lang->gitlab->group->edit}' class='btn {$adminClass}'"); - if(common::hasPriv('gitlab', 'delete')) echo html::a($this->createLink('gitlab', 'deleteGroup', "gitlabID=$gitlabID&groupID=$gitlabGroup->id"), '', 'hiddenwin', "title='{$lang->gitlab->deleteGroup}' class='btn {$adminClass}'"); + echo common::buildIconButton('gitlab', 'editGroup', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", '', 'list', 'edit', '', '', false, '', '', 0, $isAdmin); + echo common::buildIconButton('gitlab', 'deleteGroup', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", '', 'list', 'trash', 'hiddenwin', '', false, '', '', 0, $isAdmin); ?>
gitlab->project->name);?> gitlab->lastUpdate;?>actions;?>actions;?>
last_activity_at, 0, 10);?> isMaintainer ? '' : 'disabled'; - $ownerClass = $gitlabProject->adminer ? '' : 'disabled'; - $emptyBranchClass = $gitlabProject->default_branch ? '' : 'disabled'; - common::printLink('gitlab', 'browseBranch', "gitlabID=$gitlabID&projectID=$gitlabProject->id", " ", '', "title='{$lang->gitlab->browseBranch}' class='btn {$emptyBranchClass}'"); - common::printLink('gitlab', 'browseBranchPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", " ", '', "title='{$lang->gitlab->branch->accessLevel}' class='btn {$maintainerClass} {$emptyBranchClass}'"); - common::printLink('gitlab', 'browseTag', "gitlabID=$gitlabID&projectID=$gitlabProject->id", " ", '', "title='{$lang->gitlab->browseTag}' class='btn {$emptyBranchClass}'"); - common::printLink('gitlab', 'browseTagPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", " ", '', "title='{$lang->gitlab->browseTagPriv}' class='btn {$maintainerClass} {$emptyBranchClass}'"); - common::printLink('gitlab', 'editProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", " ", '', "title='{$lang->gitlab->project->edit}' class='btn {$ownerClass}'"); - if(common::hasPriv('gitlab', 'delete')) echo html::a($this->createLink('gitlab', 'deleteProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id"), '', 'hiddenwin', "title='{$lang->gitlab->deleteProject}' class='btn {$ownerClass}'"); + echo common::buildIconButton('gitlab', 'browseBranchPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'branch-lock', '', '', false, '', '', 0, ($gitlabProject->isMaintainer and $gitlabProject->default_branch)); + echo common::buildIconButton('gitlab', 'browseTagPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag-lock', '', '', false, '', '', 0, ($gitlabProject->isMaintainer and $gitlabProject->default_branch)); + echo common::buildIconButton('gitlab', 'manageProjectMembers', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'team', '', '', false, '', '', 0, isset($repoPairs[$gitlabProject->id])); + echo common::buildIconButton('gitlab', 'createWebhook', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'change', 'hiddenwin', '', false, '', '', 0, isset($repoPairs[$gitlabProject->id])); + echo common::buildIconButton('gitlab', 'importIssue', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'link', '', '', false, '', '', 0, isset($repoPairs[$gitlabProject->id])); + echo common::buildIconButton('gitlab', 'editProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'edit', '', '', false, '', '', 0, $gitlabProject->adminer); + echo common::buildIconButton('gitlab', 'deleteProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'trash', 'hiddenwin', '', false, '', '', 0, $gitlabProject->adminer); ?>
lastActivityOn, 0, 10);?> id", " ", '', "title='{$lang->gitlab->user->edit}' class='btn btn-primary'"); - if(common::hasPriv('gitlab', 'delete')) echo html::a($this->createLink('gitlab', 'deleteUser', "gitlabID=$gitlabID&userID=$gitlabUser->id"), '', 'hiddenwin', "title='{$lang->gitlab->deleteUser}' class='btn'" . ($isAdmin ? '' : ' disabled')); + echo common::buildIconButton('gitlab', 'editUser', "gitlabID=$gitlabID&userID=$gitlabUser->id", '', 'list', 'edit', '', '', false, '', '', 0, $isAdmin); + echo common::buildIconButton('gitlab', 'deleteUser', "gitlabID=$gitlabID&userID=$gitlabUser->id", '', 'list', 'trash', 'hiddenwin', '', false, '', '', 0, $isAdmin); ?>
install->password;?>install->placeholder->password}' oninput=\"this.value = this.value.replace(/[\u4e00-\u9fa5]/g, '');\"");?>install->placeholder->password}' oninput=\"this.value = this.value.replace(/[^\\x00-\\xff]/g, '');\"");?>
install->importDemoData);?> - goback, '', 'class="btn btn-wide"');?> + repo}"), $lang->goback, '', 'class="btn btn-wide"');?> repo, 'Git'));?>
email;?> app->tab == 'program') $module = 'program'; if(common::hasPriv($module, 'unbindWhitelist')) echo html::a($this->createLink($module, 'unbindWhitelist', "id=$user->id&confirm=no"), '', 'hiddenwin', "title='{$lang->personnel->delete}' class='btn' $tab"); ?>
@@ -34,7 +42,6 @@ - group->confirmDelete, $group->name);?> id]);?> @@ -52,8 +59,9 @@ role != 'limited') { - $deleteURL = $this->createLink('group', 'delete', "groupID=$group->id&confirm=yes"); - echo html::a("###", '', '', "onclick='ajaxDelete(\"$deleteURL\", \"groupList\", confirmDelete)' title='{$lang->group->delete}' class='btn btn-icon'"); + $deleteURL = $this->createLink('group', 'delete', "groupID=$group->id&confirm=yes"); + $confirmDelete = htmlspecialchars(sprintf($lang->group->confirmDelete, $group->name)); + echo html::a("###", '', '', "onclick='ajaxDelete(\"$deleteURL\", \"groupList\", \"$confirmDelete\")' title='{$lang->group->delete}' class='btn btn-icon'"); } else { @@ -65,6 +73,6 @@
id;?>
+
- diff --git a/module/project/view/testtask.html.php b/module/project/view/testtask.html.php index 2767c461f3..bae7bc849e 100644 --- a/module/project/view/testtask.html.php +++ b/module/project/view/testtask.html.php @@ -94,7 +94,7 @@ common::printIcon('testtask', 'linkCase', "taskID=$task->id", $task, 'list', 'link'); if(common::hasPriv('execution', 'testreport') and $project->model == 'scrum') { - echo html::a($this->createLink('execution', 'testreport', "executionID=$task->execution&objectType=execution&extra=$task->id"), '', '', 'class="btn " title="' . $lang->testreport->browse . '" data-app="project"'); + echo html::a($this->createLink('execution', 'testreport', "executionID=$task->execution&objectType=execution&extra=$task->id"), '', '', 'class="btn " title="' . $lang->testreport->browse . '" data-app="project"'); } common::printIcon('testtask', 'edit', "taskID=$task->id", $task, 'list'); common::printIcon('testtask', 'delete', "taskID=$task->id", $task, 'list', 'trash', 'hiddenwin'); diff --git a/module/release/view/create.html.php b/module/release/view/create.html.php index 975960dc03..1030319234 100644 --- a/module/release/view/create.html.php +++ b/module/release/view/create.html.php @@ -25,7 +25,7 @@ release->name;?> - +
diff --git a/module/repo/config.php b/module/repo/config.php index ebb573a0fe..3c258706c1 100644 --- a/module/repo/config.php +++ b/module/repo/config.php @@ -33,6 +33,9 @@ $config->repo->editor->edit = array('id' => 'desc', 'tools' => 'simpleTools'); $config->repo->editor->view = array('id' => 'commentText', 'tools' => 'simpleTools'); $config->repo->editor->diff = array('id' => 'commentText', 'tools' => 'simpleTools'); +$config->repo->switcherModuleList = array('repo', 'job', 'compile', 'mr'); +$config->repo->switcherMethodList = array('browse', 'review', 'view', 'diff', 'log', 'revision', 'blame'); + $config->repo->create = new stdclass(); $config->repo->create->requiredFields = 'product,SCM,name,path,encoding,client'; diff --git a/module/repo/control.php b/module/repo/control.php index e940ee3a82..7942fe6a84 100644 --- a/module/repo/control.php +++ b/module/repo/control.php @@ -78,9 +78,6 @@ class repo extends control */ public function maintain($objectID = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { - $this->lang->switcherMenu = ''; - if(common::hasPriv('repo', 'create')) $this->lang->TRActions = html::a(helper::createLink('repo', 'create'), " " . $this->lang->repo->create, '', "class='btn btn-primary'"); - $repoID = $this->repo->saveState(0, $objectID); if($this->viewType !== 'json') $this->commonAction($repoID, $objectID); @@ -1139,18 +1136,32 @@ class repo extends control * @access public * @return void */ - public function ajaxGetDropMenu($repoID, $type = 'repo', $objectID = 0) + public function ajaxGetDropMenu($repoID, $module = 'repo', $method = 'browse') { - $repos = $this->repo->getRepoPairs($type, $objectID); - $reposHtml = "
"; - foreach($repos as $id => $repoName) + if($module == 'mr') $method = 'browse'; + if($module == 'job') $method = 'browse'; + if($module == 'compile' and $method == 'logs') $method = 'browse'; + if($module == 'bug' and $method == 'view') { - $selected = $id == $repoID ? 'selected' : ''; - $reposHtml .= html::a($this->createLink('repo', 'browse', "repoID=$id&branchID=&objectID=$objectID"), $repoName, '', "class='$selected' data-app='{$this->app->tab}'"); + $module = 'repo'; + $method = 'review'; } - $reposHtml .= '
'; - return print($reposHtml); + /* Get repo group by type. */ + $repoGroup = $this->repo->getRepoGroup($this->app->tab); + if($module == 'mr') + { + foreach($repoGroup as $type => $group) + { + if(strtolower($type) != 'gitlab') unset($repoGroup[$type]); + } + } + + $this->view->repoID = $repoID; + $this->view->repoGroup = $repoGroup; + $this->view->link = $this->createLink($module, $method, "repoID=%s"); + + $this->display(); } /** @@ -1186,7 +1197,6 @@ class repo extends control } } - if(!$projects) $this->send(array('message' => array())); $projectIdList = $projectIdList ? explode(',', $projectIdList) : null; $options = ""; diff --git a/module/repo/css/common.css b/module/repo/css/common.css index c107a8aff7..7d19921566 100644 --- a/module/repo/css/common.css +++ b/module/repo/css/common.css @@ -191,17 +191,3 @@ h3 {font-size: 16px;} .header-btn .btn > .text {text-overflow: unset !important;} #repoPageSize {right: 90px;} - -/* Style for repo select. */ -#repoList .tree li {padding: 0 0 0 15px;} -#repoList .hide-in-search .hidden {display: block !important; visibility: inherit !important;} -#dropMenuRepo > div.table-row > div > div > ul > li > div {padding-left: 10px;} -li > a.selected {color: #3123ae !important; background: #f2eafc !important; line-height: 20px; border-radius: 5px;} -#repoList .tree li.has-list.open:before {border-left: 0px;} -#repoList ul.tree-angles {margin-bottom: 0;} -#repoList {margin: 0;} -#repoList .tree > li {padding: 2px;} -.pull-left ul > li > ul > li > a:hover {color: white; background-color: #0c64eb; text-decoration: none;} -.pull-left .tree li > a {max-width: 100%;} -#repoList .hide-in-search .hidden {display: block !important; visibility: inherit !important;} -#repoList .tree li > a {line-height: 20px; border-radius: 2px;} diff --git a/module/repo/lang/zh-cn.php b/module/repo/lang/zh-cn.php index f3e816862d..c59dcf047b 100644 --- a/module/repo/lang/zh-cn.php +++ b/module/repo/lang/zh-cn.php @@ -5,9 +5,9 @@ $lang->repo->viewRevision = '查看修订'; $lang->repo->product = '所属产品'; $lang->repo->execution = '所属' . $lang->execution->common; $lang->repo->create = '创建'; -$lang->repo->maintain = '版本库列表'; +$lang->repo->maintain = '代码库列表'; $lang->repo->edit = '编辑'; -$lang->repo->delete = '删除版本库'; +$lang->repo->delete = '删除代码库'; $lang->repo->showSyncCommit = '显示同步进度'; $lang->repo->ajaxSyncCommit = '接口:AJAX同步注释'; $lang->repo->setRules = '指令配置'; @@ -25,11 +25,11 @@ $lang->repo->parent = '父文件夹'; $lang->repo->branch = '分支'; $lang->repo->tag = '标签'; $lang->repo->addWebHook = '添加Webhook'; -$lang->repo->apiGetRepoByUrl = '接口:通过URL获取版本库'; +$lang->repo->apiGetRepoByUrl = '接口:通过URL获取代码库'; -$lang->repo->browseAction = '浏览版本库'; -$lang->repo->createAction = '创建版本库'; -$lang->repo->editAction = '编辑版本库'; +$lang->repo->browseAction = '浏览代码库'; +$lang->repo->createAction = '创建代码库'; +$lang->repo->editAction = '编辑代码库'; $lang->repo->diffAction = '版本对比'; $lang->repo->downloadAction = '下载代码库文件'; $lang->repo->revisionAction = '版本详情'; @@ -149,8 +149,8 @@ $lang->repo->notice = new stdclass(); $lang->repo->notice->syncing = '正在同步中, 请稍等...'; $lang->repo->notice->syncComplete = '同步完成,正在跳转...'; $lang->repo->notice->syncedCount = '已经同步记录条数'; -$lang->repo->notice->delete = '是否要删除该版本库?'; -$lang->repo->notice->successDelete = '已经成功删除版本库。'; +$lang->repo->notice->delete = '是否要删除该代码库?'; +$lang->repo->notice->successDelete = '已经成功删除代码库。'; $lang->repo->notice->commentContent = '输入回复内容'; $lang->repo->notice->deleteReview = '确认删除该评审?'; $lang->repo->notice->deleteBug = '确认删除该Bug?'; @@ -166,9 +166,9 @@ $lang->repo->rules->example['bug']['resolve'] = "%resolve% %bug% %id%1%split%2"; $lang->repo->error = new stdclass(); $lang->repo->error->useless = '你的服务器禁用了exec,shell_exec方法,无法使用该功能'; -$lang->repo->error->connect = '连接版本库失败,请填写正确的用户名、密码和版本库地址!'; +$lang->repo->error->connect = '连接代码库失败,请填写正确的用户名、密码和代码库地址!'; $lang->repo->error->version = "https和svn协议需要1.8及以上版本的客户端,请升级到最新版本!详情访问:http://subversion.apache.org/"; -$lang->repo->error->path = '版本库地址直接填写文件路径,如:/home/test。'; +$lang->repo->error->path = '代码库地址直接填写文件路径,如:/home/test。'; $lang->repo->error->cmd = '客户端错误!'; $lang->repo->error->diff = '必须选择两个版本'; $lang->repo->error->safe = '因为安全原因,需要检测客户端版本,请将版本号写入文件 %s
可以执行命令:%s'; @@ -176,19 +176,19 @@ $lang->repo->error->product = "请选择{$lang->productCommon}!"; $lang->repo->error->commentText = '请填写评审内容'; $lang->repo->error->comment = '请填写内容'; $lang->repo->error->title = '请填写标题'; -$lang->repo->error->accessDenied = '你没有权限访问该版本库'; -$lang->repo->error->noFound = '你访问的版本库不存在'; +$lang->repo->error->accessDenied = '你没有权限访问该代码库'; +$lang->repo->error->noFound = '你访问的代码库不存在'; $lang->repo->error->noFile = '目录 %s 不存在'; $lang->repo->error->noPriv = '程序没有权限切换到目录 %s'; $lang->repo->error->output = "执行命令:%s\n错误结果(%s): %s\n"; $lang->repo->error->clientVersion = "客户端版本过低,请升级或更换SVN客户端"; $lang->repo->error->encoding = "编码可能错误,请更换编码重试。"; -$lang->repo->error->deleted = "删除版本库失败,当前版本库有提交记录与设计关联"; -$lang->repo->error->linkedJob = "删除版本库失败,当前版本库与构建有关联,请取消关联或删除构建。"; +$lang->repo->error->deleted = "删除代码库失败,当前代码库有提交记录与设计关联"; +$lang->repo->error->linkedJob = "删除代码库失败,当前代码库与构建有关联,请取消关联或删除构建。"; $lang->repo->error->clientPath = "客户端安装目录不能有空格!"; -$lang->repo->error->notFound = "版本库『%s』路径 %s 不存在,请确认此版本库是否已在本地服务器被删除"; +$lang->repo->error->notFound = "代码库『%s』路径 %s 不存在,请确认此代码库是否已在本地服务器被删除"; -$lang->repo->syncTips = '请参照这里,设置版本库定时同步。'; +$lang->repo->syncTips = '请参照这里,设置代码库定时同步。'; $lang->repo->encodingsTips = "提交日志的编码,可以用逗号连接起来的多个,比如utf-8。"; $lang->repo->pathTipsForGitlab = "GitLab 项目URL"; @@ -200,7 +200,7 @@ $lang->repo->example->client->svn = "例如:/usr/bin/svn"; $lang->repo->example->path->git = "例如:/home/user/myproject"; $lang->repo->example->path->svn = "例如:http://example.googlecode.com/svn/trunk/myproject"; $lang->repo->example->config = "https需要填写配置目录的位置,通过config-dir选项生成配置目录"; -$lang->repo->example->encoding = "填写版本库中文件的编码"; +$lang->repo->example->encoding = "填写代码库中文件的编码"; $lang->repo->typeList['standard'] = '规范'; $lang->repo->typeList['performance'] = '性能'; diff --git a/module/repo/model.php b/module/repo/model.php index c5fcfa2945..390d4a8414 100644 --- a/module/repo/model.php +++ b/module/repo/model.php @@ -35,7 +35,6 @@ class repoModel extends model */ public function setMenu($repos, $repoID = '', $showSeleter = true) { - if(empty($repos)) $this->lang->switcherMenu = ''; if(empty($repoID)) $repoID = $this->session->repoID ? $this->session->repoID : key($repos); if(!isset($repos[$repoID])) $repoID = key($repos); @@ -56,6 +55,8 @@ class repoModel extends model } } + $this->lang->switcherMenu = $this->getSwitcher($repoID); + common::setMenuVars('devops', $repoID); if(!session_id()) session_start(); $this->session->set('repoID', $repoID); @@ -63,54 +64,34 @@ class repoModel extends model } /** - * Create the select code of repos. + * Get switcher. * - * @param array $repos - * @param int $repoID - * @param string $type - * @param int $objectID + * @param int $repoID * @access public * @return string */ - public function select($repos, $repoID, $type = 'repo', $objectID = 0) + public function getSwitcher($repoID) { - $output = ''; - if(!empty($repos)) + $currentModule = $this->app->moduleName; + $currentMethod = $this->app->methodName; + if(!in_array($currentModule, $this->config->repo->switcherModuleList)) return ''; + if($currentModule == 'repo' and !in_array($currentMethod, $this->config->repo->switcherMethodList)) return ''; + + $currentRepo = $this->getRepoByID($repoID); + $currentRepoName = $currentRepo->name; + + if($this->app->viewType == 'mhtml' and $repoID) { - $dropMenuLink = helper::createLink('repo', 'ajaxGetDropMenu', "repoID=$repoID&type=$type&objectID=$objectID"); - - $repo = $this->dao->findById($repoID)->from(TABLE_REPO)->fetch(); - $scm = $repo->SCM == 'Subversion' ? 'svn' : 'git'; - - $output = "
"; - - $branches = $this->getBranches($repo); - if(empty($branches)) - { - $this->setRepoBranch(''); - } - else - { - $branchID = 'master'; - if($this->cookie->repoBranch) $branchID = $this->cookie->repoBranch; - if(!isset($branches[$branchID])) $branchID = 'master'; - - $branch = zget($branches, $branchID); - if(empty($branch)) $branchID = $branch = current($branches); - - $this->setRepoBranch($branchID); - - $branchName = isset($branches[$branch]) ? $branches[$branch] : $branches[0]; - - $dropMenuLink = helper::createLink('repo', 'ajaxGetBranchDropMenu', "repID=$repoID&branchID=" . base64_encode($branchID) . "&objectID=$objectID"); - $output .= "
"; - } + $output = $this->lang->repo->common . $this->lang->colon; + $output .= "{$currentRepoName} "; + return $output; } + $dropMenuLink = helper::createLink('repo', 'ajaxGetDropMenu', "repoID=$repoID&module=$currentModule&method=$currentMethod"); + + $output = "
"; + return $output; } @@ -220,7 +201,16 @@ class repoModel extends model ->join('product', ',') ->get(); - if($this->post->SCM == 'Gitlab') $data->path = $this->post->gitlabProject; + if($this->post->SCM == 'Gitlab') + { + $repo = $this->dao->select('id')->from(TABLE_REPO) + ->where('SCM')->eq('Gitlab') + ->andWhere('client')->eq($data->client) + ->andWhere('path')->eq($data->path) + ->fetch(); + if(!empty($repo)) dao::$errors['gitlabProject'] = sprintf($this->lang->error->unique, $this->lang->repo->gitlabProject, $repo->id); + if(dao::isError()) return false; + } $data->acl = empty($data->acl) ? '' : json_encode($data->acl); @@ -239,6 +229,8 @@ class repoModel extends model ->batchCheck($this->config->repo->create->requiredFields, 'notempty') ->checkIF($data->SCM == 'Gitlab', 'gitlabProject', 'notempty') ->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty') + ->checkIF($data->SCM == 'Git', 'path', 'unique', "`SCM` = 'Git'") + ->checkIF($data->SCM == 'Subversion', 'path', 'unique', "`SCM` = 'Subversion'") ->autoCheck() ->exec(); @@ -306,6 +298,18 @@ class repoModel extends model $data->prefix = ''; } + if($this->post->SCM == 'Gitlab') + { + $repo = $this->dao->select('id')->from(TABLE_REPO) + ->where('SCM')->eq('Gitlab') + ->andWhere('client')->eq($data->client) + ->andWhere('path')->eq($data->path) + ->andWhere('id')->ne($id) + ->fetch(); + if(!empty($repo)) dao::$errors['gitlabProject'] = sprintf($this->lang->error->unique, $this->lang->repo->gitlabProject, $repo->id); + if(dao::isError()) return false; + } + if($data->client != $repo->client and !$this->checkClient()) return false; if(!$this->checkConnection()) return false; @@ -314,6 +318,8 @@ class repoModel extends model ->batchCheck($this->config->repo->edit->requiredFields, 'notempty') ->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty') ->checkIF($data->SCM == 'Gitlab', 'extra', 'notempty') + ->checkIF($data->SCM == 'Git', 'path', 'unique', "`SCM` = 'Git' and `id` <> $id") + ->checkIF($data->SCM == 'Subversion', 'path', 'unique', "`SCM` = 'Subversion' and `id` <> $id") ->autoCheck() ->where('id')->eq($id)->exec(); @@ -2034,13 +2040,13 @@ class repoModel extends model * @param int $projectID * @return array */ - public function getGitLabRepoList($gitlabID, $projectID) + public function getGitLabRepoList($gitlabID, $projectID = 0) { return $this->dao->select('*')->from(TABLE_REPO)->where('deleted')->eq('0') ->andWhere('SCM')->eq('Gitlab') ->andWhere('synced')->eq(1) ->andWhere('client')->eq($gitlabID) - ->andWhere('path')->eq($projectID) + ->beginIF($projectID)->andWhere('path')->eq($projectID)->fi() ->fetchAll(); } @@ -2125,65 +2131,4 @@ class repoModel extends model foreach($executions as $execution) $pairs[$execution->id] = $execution->name; return $pairs; } - - /** - * Get repos select menu. - * - * @param object $repo - * @param int $objectID - * @param string $link - * @param string $scm - * @access public - * @return void - */ - public function getReposMenu($repo, $objectID = 0, $link = '', $scm = '') - { - if(empty($link)) $link = helper::createLink('repo', 'browse', "repoID=%s&branchID=&objectID=$objectID"); - $html = ""; - $html .= "'; - return $html; - } } diff --git a/module/repo/view/ajaxgetdropmenu.html.php b/module/repo/view/ajaxgetdropmenu.html.php new file mode 100644 index 0000000000..fd13277e08 --- /dev/null +++ b/module/repo/view/ajaxgetdropmenu.html.php @@ -0,0 +1,60 @@ + + * @package repo + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+
+
+ +
+
+
+ diff --git a/module/repo/view/browse.html.php b/module/repo/view/browse.html.php index 540f2e3015..853959ab83 100644 --- a/module/repo/view/browse.html.php +++ b/module/repo/view/browse.html.php @@ -11,9 +11,6 @@