Merge branch 'sprint/185' into 'sprint/185_zhengrunyu_49283'

# Conflicts:
#   db/update16.4.sql
#   module/user/view/story.html.php
This commit is contained in:
李玉春
2022-02-23 01:33:37 +00:00
319 changed files with 11572 additions and 1545 deletions
+6 -1
View File
@@ -12,8 +12,12 @@ tmp/log/*
tmp/model/*
tmp/cache/*
tmp/extension/*
extension/pro/*
extension/biz/*
extension/max/*
extension/xuan/*
extension/custom/*
test/data/sql/
.gitkeep
.bak
.idea
.vscode
@@ -27,3 +31,4 @@ composer.lock
CodeSniffer.conf
test/runtime/*
test/www
!/**/.gitkeep
+3 -3
View File
@@ -286,7 +286,7 @@ class userEntry extends Entry
$info->issue = array('total' => 0, 'issues' => array());
if(!common::hasPriv('my', 'issue')) break;
if(!empty($this->config->maxVersion))
if($this->config->edition == 'max')
{
$control = $this->loadController('my', 'issue');
$control->issue('createdBy', 'id_desc', 0, $this->param('limit', 5), 1);
@@ -303,7 +303,7 @@ class userEntry extends Entry
$info->risk = array('total' => 0, 'risks' => array());
if(!common::hasPriv('my', 'risk')) break;
if(!empty($this->config->maxVersion))
if($this->config->edition == 'max')
{
$control = $this->loadController('my', 'risk');
$control->risk('createdBy', 'id_desc', 0, $this->param('limit', 5), 1);
@@ -320,7 +320,7 @@ class userEntry extends Entry
$info->meeting = array('total' => 0, 'meetings' => array());
if(!common::hasPriv('my', 'myMeeting')) break;
if(!empty($this->config->maxVersion))
if($this->config->edition == 'max')
{
$control = $this->loadController('my', 'myMeeting');
$control->myMeeting('all', 'id_desc', 0, $this->param('limit', 5), 1);
+10 -1
View File
@@ -16,12 +16,13 @@ if(!class_exists('config')){class config{}}
if(!function_exists('getWebRoot')){function getWebRoot(){}}
/* 基本设置。Basic settings. */
$config->version = '16.4'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->version = '16.5'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
$config->timezone = 'Asia/Shanghai'; // 时区设置。 The time zone setting, for more see http://www.php.net/manual/en/timezones.php.
$config->webRoot = ''; // URL根目录。 The root path of the url.
$config->customSession = false; // 是否开启自定义session的存储路径。Whether custom the session save path.
$config->edition = 'open'; // 设置系统的edition,可选值:open|biz|max。Set edition, optional: open|biz|max.
/* 框架路由相关设置。Routing settings. */
$config->requestType = 'PATH_INFO'; // 请求类型:PATH_INFO|PATHINFO2|GET。 The request type: PATH_INFO|PATH_INFO2|GET.
@@ -31,6 +32,7 @@ $config->methodVar = 'f'; // 请求类型为GET:模块
$config->viewVar = 't'; // 请求类型为GET:视图变量名。 requestType=GET: the view var name.
$config->sessionVar = 'zentaosid'; // 请求类型为GETsession变量名。 requestType=GET: the session var name.
$config->views = ',html,json,mhtml,xhtml,'; // 支持的视图类型。 Supported view formats.
$config->visions = ',rnd,lite,'; // 支持的界面类型。 Supported vision formats.
/* 支持的主题和语言。Supported thems and languages. */
$config->themes['default'] = 'default';
@@ -177,3 +179,10 @@ if(file_exists($routesConfig)) include $routesConfig;
/* Include extension config files. */
$extConfigFiles = glob(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'ext/*.php');
if($extConfigFiles) foreach($extConfigFiles as $extConfigFile) include $extConfigFile;
/* Set version. */
if($config->edition != 'open')
{
$config->version = $config->edition . $config->{$config->edition . 'Version'};
if($config->edition != 'max') unset($config->maxVersion);
}
+5 -2
View File
@@ -1,4 +1,4 @@
ALTER TABLE `zt_userquery` ADD`common` enum('0','1') NOT NULL DEFAULT '0';
ALTER TABLE `zt_userquery` ADD `common` enum('0','1') NOT NULL DEFAULT '0';
ALTER TABLE `zt_project` ADD `vision` varchar(10) NOT NULL DEFAULT 'rnd' AFTER `order`;
ALTER TABLE `zt_product` ADD `vision` varchar(10) NOT NULL DEFAULT 'rnd' AFTER `order`;
@@ -19,5 +19,8 @@ ALTER TABLE `zt_block` DROP INDEX `account_module_type_order`, ADD UNIQUE `accou
ALTER TABLE `zt_effort` ADD `vision` varchar(10) NOT NULL DEFAULT 'rnd' AFTER `id`;
ALTER TABLE `zt_story` ADD `vision` varchar(10) NOT NULL DEFAULT 'rnd' AFTER `id`;
ALTER TABLE `zt_story` ADD `activatedDate` datetime NOT NULL AFTER `closedReason`;
ALTER TABLE `zt_task` MODIFY `activatedDate` datetime NOT NULL AFTER `lastEditedDate`;
ALTER TABLE `zt_user` ADD `visions` varchar(20) NOT NULL AFTER `visits`;
UPDATE `zt_user` SET `visions`='rnd,lite';
UPDATE `zt_user` SET `visions`='rnd,lite';
+250 -6
View File
@@ -22,6 +22,7 @@ CREATE TABLE IF NOT EXISTS `zt_action` (
`comment` text NOT NULL,
`extra` text NOT NULL,
`read` enum('0','1') NOT NULL default '0',
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
PRIMARY KEY (`id`),
KEY `date` (`date`),
KEY `actor` (`actor`),
@@ -123,6 +124,7 @@ CREATE TABLE `zt_apistruct_spec` (
CREATE TABLE IF NOT EXISTS `zt_block` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`account` char(30) NOT NULL,
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
`module` varchar(20) NOT NULL,
`type` char(30) NOT NULL,
`title` varchar(100) NOT NULL,
@@ -134,7 +136,7 @@ CREATE TABLE IF NOT EXISTS `zt_block` (
`height` smallint(5) unsigned NOT NULL DEFAULT '0',
`hidden` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `account_module_type_order` (`account`,`module`,`type`,`order`),
UNIQUE KEY `account_vision_module_type_order` (`account`,`vision`,`module`,`type`,`order`),
KEY `account` (`account`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_branch`;
@@ -357,13 +359,14 @@ CREATE TABLE IF NOT EXISTS `zt_compile` (
-- DROP TABLE IF EXISTS `zt_config`;
CREATE TABLE IF NOT EXISTS `zt_config` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`vision` varchar(10) NOT NULL DEFAULT '',
`owner` char(30) NOT NULL default '',
`module` varchar(30) NOT NULL,
`section` char(30) NOT NULL default '',
`key` char(30) NOT NULL default '',
`value` longtext NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique` (`owner`,`module`,`section`,`key`)
UNIQUE KEY `unique` (`vision`,`owner`,`module`,`section`,`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_cron`;
CREATE TABLE IF NOT EXISTS `zt_cron` (
@@ -433,6 +436,7 @@ CREATE TABLE IF NOT EXISTS `zt_designspec` (
-- DROP TABLE IF EXISTS `zt_doc`;
CREATE TABLE IF NOT EXISTS `zt_doc` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
`project` mediumint(8) unsigned NOT NULL,
`product` mediumint(8) unsigned NOT NULL,
`execution` mediumint(8) unsigned NOT NULL,
@@ -476,6 +480,7 @@ CREATE TABLE IF NOT EXISTS `zt_doccontent` (
CREATE TABLE IF NOT EXISTS `zt_doclib` (
`id` smallint(5) unsigned NOT NULL auto_increment,
`type` varchar(30) NOT NULL,
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
`product` mediumint(8) unsigned NOT NULL,
`project` mediumint(8) unsigned NOT NULL,
`execution` mediumint(8) unsigned NOT NULL,
@@ -582,6 +587,7 @@ CREATE TABLE IF NOT EXISTS `zt_file` (
CREATE TABLE IF NOT EXISTS `zt_group` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`project` mediumint(8) unsigned NOT NULL DEFAULT 0,
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
`name` char(30) NOT NULL,
`role` char(30) NOT NULL default '',
`desc` char(255) NOT NULL default '',
@@ -801,8 +807,9 @@ CREATE TABLE IF NOT EXISTS `zt_lang` (
`key` varchar(60) NOT NULL,
`value` text NOT NULL,
`system` enum('0','1') NOT NULL default '1',
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
PRIMARY KEY (`id`),
UNIQUE KEY `lang` (`lang`,`module`,`section`,`key`)
UNIQUE KEY `lang` (`lang`,`module`,`section`,`key`,`vision`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_log`;
CREATE TABLE IF NOT EXISTS `zt_log` (
@@ -958,6 +965,7 @@ CREATE TABLE IF NOT EXISTS `zt_product` (
`createdDate` datetime NOT NULL,
`createdVersion` varchar(20) NOT NULL,
`order` mediumint(8) unsigned NOT NULL,
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
`deleted` enum('0','1') NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `acl` (`acl`),
@@ -1030,6 +1038,7 @@ CREATE TABLE IF NOT EXISTS `zt_project` (
`acl` char(30) NOT NULL DEFAULT 'open',
`whitelist` text NOT NULL,
`order` mediumint(8) unsigned NOT NULL,
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
`displayCards` smallint(6) NOT NULL default '0',
`fluidBoard` enum('0','1') NOT NULL DEFAULT '0',
`deleted` enum('0','1') NOT NULL DEFAULT '0',
@@ -1077,7 +1086,8 @@ CREATE TABLE IF NOT EXISTS `zt_projectstory` (
`story` mediumint(8) unsigned NOT NULL default '0',
`version` smallint(6) NOT NULL default '1',
`order` smallint(6) unsigned NOT NULL,
UNIQUE KEY `project` (`project`,`story`)
UNIQUE KEY `project` (`project`,`story`),
KEY `story` (`story`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_relation`;
CREATE TABLE IF NOT EXISTS `zt_relation` (
@@ -1208,6 +1218,7 @@ CREATE TABLE IF NOT EXISTS `zt_searchdict` (
-- DROP TABLE IF EXISTS `zt_searchindex`;
CREATE TABLE IF NOT EXISTS `zt_searchindex` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
`objectType` char(20) NOT NULL,
`objectID` mediumint(9) NOT NULL,
`title` text NOT NULL,
@@ -1282,6 +1293,7 @@ CREATE TABLE IF NOT EXISTS `zt_story` (
`closedBy` varchar(30) NOT NULL default '',
`closedDate` datetime NOT NULL,
`closedReason` varchar(30) NOT NULL,
`activatedDate` datetime NOT NULL,
`toBug` mediumint(8) unsigned NOT NULL,
`childStories` varchar(255) NOT NULL,
`linkStories` varchar(255) NOT NULL,
@@ -1384,7 +1396,7 @@ CREATE TABLE IF NOT EXISTS `zt_task` (
`closedReason` varchar(30) NOT NULL,
`lastEditedBy` varchar(30) NOT NULL,
`lastEditedDate` datetime NOT NULL,
`activatedDate` date NOT NULL,
`activatedDate` datetime NOT NULL,
`repo` mediumint(8) unsigned NOT NULL,
`mr` mediumint(8) unsigned NOT NULL,
`entry` varchar(255) NOT NULL,
@@ -1392,7 +1404,8 @@ CREATE TABLE IF NOT EXISTS `zt_task` (
`v1` varchar(40) NOT NULL,
`v2` varchar(40) NOT NULL,
`deleted` enum('0','1') NOT NULL default '0',
PRIMARY KEY (`id`),
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
PRIMARY KEY (`id`),
KEY `execution` (`execution`),
KEY `story` (`story`),
KEY `parent` (`parent`),
@@ -1560,6 +1573,7 @@ CREATE TABLE IF NOT EXISTS `zt_todo` (
`closedBy` varchar(30) NOT NULL DEFAULT '',
`closedDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL default '0',
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
PRIMARY KEY (`id`),
KEY `account` (`account`),
KEY `assignedTo` (`assignedTo`),
@@ -1637,6 +1651,7 @@ CREATE TABLE IF NOT EXISTS `zt_userquery` (
`form` text NOT NULL,
`sql` text NOT NULL,
`shortcut` enum('0','1') NOT NULL DEFAULT '0',
`common` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `account` (`account`),
KEY `module` (`module`)
@@ -1731,6 +1746,9 @@ INSERT INTO `zt_group` (`id`, `name`, `role`, `desc`) VALUES
(12, 'LIMITED', 'limited', 'For limited user'),
(13, 'PROJECTADMIN', 'projectAdmin', 'Project Admins manage project privileges');
INSERT INTO `zt_group` (`id`, `vision`, `name`, `role`, `desc`) VALUES
(14, 'lite', 'LITEUSER', 'liteUser', 'Normal user of lite vision');
INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(1,'action','comment'),
(1,'action','editComment'),
@@ -5958,6 +5976,232 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(11,'user','view'),
(12,'my','limited');
INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(14,'action','comment'),
(14,'action','editComment'),
(14,'action','trash'),
(14,'action','undelete'),
(14,'admin','checkWeak'),
(14,'admin','index'),
(14,'admin','safe'),
(14,'api','debug'),
(14,'company','browse'),
(14,'company','dynamic'),
(14,'company','edit'),
(14,'company','index'),
(14,'company','view'),
(14,'custom','execution'),
(14,'custom','flow'),
(14,'custom','index'),
(14,'custom','product'),
(14,'custom','restore'),
(14,'custom','set'),
(14,'custom','setPublic'),
(14,'datatable','setGlobal'),
(14,'dept','browse'),
(14,'dept','delete'),
(14,'dept','edit'),
(14,'dept','manageChild'),
(14,'dept','updateOrder'),
(14,'dev','api'),
(14,'dev','db'),
(14,'dev','editor'),
(14,'doc','allLibs'),
(14,'doc','browse'),
(14,'doc','collect'),
(14,'doc','create'),
(14,'doc','createLib'),
(14,'doc','delete'),
(14,'doc','deleteFile'),
(14,'doc','deleteLib'),
(14,'doc','edit'),
(14,'doc','editLib'),
(14,'doc','index'),
(14,'doc','objectLibs'),
(14,'doc','showFiles'),
(14,'doc','tableContents'),
(14,'doc','view'),
(14,'execution','all'),
(14,'execution','browse'),
(14,'execution','bug'),
(14,'execution','build'),
(14,'execution','burn'),
(14,'execution','burnData'),
(14,'execution','computeBurn'),
(14,'execution','doc'),
(14,'execution','dynamic'),
(14,'execution','executionkanban'),
(14,'execution','fixFirst'),
(14,'execution','grouptask'),
(14,'execution','kanban'),
(14,'execution','manageMembers'),
(14,'execution','printKanban'),
(14,'execution','story'),
(14,'execution','storyEstimate'),
(14,'execution','storyKanban'),
(14,'execution','task'),
(14,'execution','team'),
(14,'execution','tree'),
(14,'execution','treeStory'),
(14,'execution','treeTask'),
(14,'execution','view'),
(14,'execution','whitelist'),
(14,'file','delete'),
(14,'file','download'),
(14,'file','edit'),
(14,'file','setPublic'),
(14,'file','uploadImages'),
(14,'group','browse'),
(14,'index','index'),
(14,'message','browser'),
(14,'message','index'),
(14,'message','setting'),
(14,'misc','ping'),
(14,'my','bug'),
(14,'my','calendar'),
(14,'my','changePassword'),
(14,'my','contribute'),
(14,'my','deleteContacts'),
(14,'my','doc'),
(14,'my','dynamic'),
(14,'my','editProfile'),
(14,'my','execution'),
(14,'my','index'),
(14,'my','manageContacts'),
(14,'my','preference'),
(14,'my','profile'),
(14,'my','project'),
(14,'my','score'),
(14,'my','story'),
(14,'my','task'),
(14,'my','team'),
(14,'my','todo'),
(14,'my','uploadAvatar'),
(14,'my','work'),
(14,'personnel','accessible'),
(14,'personnel','invest'),
(14,'personnel','whitelist'),
(14,'product','all'),
(14,'product','browse'),
(14,'product','build'),
(14,'product','dashboard'),
(14,'product','dynamic'),
(14,'product','index'),
(14,'product','kanban'),
(14,'product','project'),
(14,'product','roadmap'),
(14,'product','view'),
(14,'product','whitelist'),
(14,'productplan','browse'),
(14,'productplan','view'),
(14,'program','browse'),
(14,'program','kanban'),
(14,'program','product'),
(14,'program','project'),
(14,'program','stakeholder'),
(14,'program','view'),
(14,'project','browse'),
(14,'project','bug'),
(14,'project','build'),
(14,'project','create'),
(14,'project','dynamic'),
(14,'project','edit'),
(14,'project','execution'),
(14,'project','index'),
(14,'project','kanban'),
(14,'project','manageMembers'),
(14,'project','programTitle'),
(14,'project','qa'),
(14,'project','team'),
(14,'project','testcase'),
(14,'project','testreport'),
(14,'project','testtask'),
(14,'project','view'),
(14,'project','whitelist'),
(14,'projectbuild','browse'),
(14,'projectrelease','browse'),
(14,'projectrelease','view'),
(14,'projectstory','story'),
(14,'projectstory','track'),
(14,'projectstory','view'),
(14,'report','bugAssign'),
(14,'report','bugCreate'),
(14,'report','index'),
(14,'report','productSummary'),
(14,'report','projectDeviation'),
(14,'report','workload'),
(14,'search','buildForm'),
(14,'search','buildIndex'),
(14,'search','buildQuery'),
(14,'search','deleteQuery'),
(14,'search','index'),
(14,'search','saveQuery'),
(14,'search','select'),
(14,'story','bugs'),
(14,'story','cases'),
(14,'story','report'),
(14,'story','tasks'),
(14,'story','track'),
(14,'story','view'),
(14,'task','activate'),
(14,'task','assignTo'),
(14,'task','batchAssignTo'),
(14,'task','batchCancel'),
(14,'task','batchChangeModule'),
(14,'task','batchClose'),
(14,'task','batchCreate'),
(14,'task','batchEdit'),
(14,'task','cancel'),
(14,'task','close'),
(14,'task','confirmStoryChange'),
(14,'task','create'),
(14,'task','delete'),
(14,'task','deleteEstimate'),
(14,'task','edit'),
(14,'task','editEstimate'),
(14,'task','export'),
(14,'task','finish'),
(14,'task','pause'),
(14,'task','recordEstimate'),
(14,'task','report'),
(14,'task','restart'),
(14,'task','start'),
(14,'task','view'),
(14,'todo','activate'),
(14,'todo','assignTo'),
(14,'todo','batchClose'),
(14,'todo','batchCreate'),
(14,'todo','batchEdit'),
(14,'todo','batchFinish'),
(14,'todo','close'),
(14,'todo','create'),
(14,'todo','createcycle'),
(14,'todo','delete'),
(14,'todo','edit'),
(14,'todo','export'),
(14,'todo','finish'),
(14,'todo','import2Today'),
(14,'todo','start'),
(14,'todo','view'),
(14,'tree','browse'),
(14,'tree','browseTask'),
(14,'tree','delete'),
(14,'tree','edit'),
(14,'tree','fix'),
(14,'tree','manageChild'),
(14,'tree','updateOrder'),
(14,'user','batchEdit'),
(14,'user','cropAvatar'),
(14,'user','dynamic'),
(14,'user','execution'),
(14,'user','issue'),
(14,'user','profile'),
(14,'user','risk'),
(14,'user','story'),
(14,'user','task'),
(14,'user','todo'),
(14,'user','view');
REPLACE INTO `zt_lang` (`lang`, `module`, `section`, `key`, `value`, `system`) VALUES
('zh-cn', 'custom', 'URSRList', '1', '{\"SRName\":\"\\u8f6f\\u4ef6\\u9700\\u6c42\",\"URName\":\"\\u7528\\u6237\\u9700\\u6c42\"}', '1'),('zh-cn', 'custom', 'URSRList', '2', '{\"SRName\":\"\\u7814\\u53d1\\u9700\\u6c42\",\"URName\":\"\\u7528\\u6237\\u9700\\u6c42\"}', '1'),
('zh-cn', 'custom', 'URSRList', '3', '{\"SRName\":\"\\u8f6f\\u9700\",\"URName\":\"\\u7528\\u9700\"}', '1'),('zh-cn', 'custom', 'URSRList', '4', '{\"SRName\":\"\\u6545\\u4e8b\",\"URName\":\"\\u53f2\\u8bd7\"}', '1'),
View File
@@ -0,0 +1,89 @@
<?php
$lang->action->label->execution = "看板|execution|task|executionID=%s";
$lang->action->label->task = '任务|task|view|taskID=%s';
$lang->action->objectTypes['task'] = '任务';
unset($lang->action->dynamicAction->program);
unset($lang->action->dynamicAction->product);
unset($lang->action->dynamicAction->productplan);
unset($lang->action->dynamicAction->release);
unset($lang->action->dynamicAction->build);
unset($lang->action->dynamicAction->bug);
unset($lang->action->dynamicAction->testtask);
unset($lang->action->dynamicAction->case);
unset($lang->action->dynamicAction->testreport);
unset($lang->action->dynamicAction->testsuite);
unset($lang->action->dynamicAction->caselib);
$lang->action->dynamicAction->task = array();
$lang->action->dynamicAction->task['opened'] = '创建任务';
$lang->action->dynamicAction->task['edited'] = '编辑任务';
$lang->action->dynamicAction->task['commented'] = '备注任务';
$lang->action->dynamicAction->task['assigned'] = '指派任务';
$lang->action->dynamicAction->task['confirmed'] = "确认{$lang->SRCommon}变更";
$lang->action->dynamicAction->task['started'] = '开始任务';
$lang->action->dynamicAction->task['finished'] = '完成任务';
$lang->action->dynamicAction->task['recordestimate'] = '记录工时';
$lang->action->dynamicAction->task['editestimate'] = '编辑工时';
$lang->action->dynamicAction->task['deleteestimate'] = '删除工时';
$lang->action->dynamicAction->task['paused'] = '暂停任务';
$lang->action->dynamicAction->task['closed'] = '关闭任务';
$lang->action->dynamicAction->task['canceled'] = '取消任务';
$lang->action->dynamicAction->task['activated'] = '激活任务';
$lang->action->dynamicAction->task['createchildren'] = '创建子任务';
$lang->action->dynamicAction->task['unlinkparenttask'] = '从父任务取消关联';
$lang->action->dynamicAction->task['deletechildrentask'] = '删除子任务';
$lang->action->dynamicAction->task['linkparenttask'] = '关联到父任务';
$lang->action->dynamicAction->task['linkchildtask'] = '关联子任务';
$lang->action->search->label = array();
$lang->action->search->label[''] = '';
$lang->action->search->label['created'] = $lang->action->label->created;
$lang->action->search->label['opened'] = $lang->action->label->opened;
$lang->action->search->label['changed'] = $lang->action->label->changed;
$lang->action->search->label['edited'] = $lang->action->label->edited;
$lang->action->search->label['assigned'] = $lang->action->label->assigned;
$lang->action->search->label['closed'] = $lang->action->label->closed;
$lang->action->search->label['deleted'] = $lang->action->label->deleted;
$lang->action->search->label['deletedfile'] = $lang->action->label->deletedfile;
$lang->action->search->label['editfile'] = $lang->action->label->editfile;
$lang->action->search->label['erased'] = $lang->action->label->erased;
$lang->action->search->label['undeleted'] = $lang->action->label->undeleted;
$lang->action->search->label['hidden'] = $lang->action->label->hidden;
$lang->action->search->label['commented'] = $lang->action->label->commented;
$lang->action->search->label['activated'] = $lang->action->label->activated;
$lang->action->search->label['reviewed'] = $lang->action->label->reviewed;
$lang->action->search->label['moved'] = $lang->action->label->moved;
$lang->action->search->label['confirmed'] = $lang->action->label->confirmed;
$lang->action->search->label['totask'] = $lang->action->label->totask;
$lang->action->search->label['changestatus'] = $lang->action->label->changestatus;
$lang->action->search->label['marked'] = $lang->action->label->marked;
$lang->action->search->label['linked2project'] = $lang->action->label->linked2project;
$lang->action->search->label['unlinkedfromproject'] = $lang->action->label->unlinkedfromproject;
$lang->action->search->label['linked2execution'] = $lang->action->label->linked2execution;
$lang->action->search->label['unlinkedfromexecution'] = $lang->action->label->unlinkedfromexecution;
$lang->action->search->label['started'] = $lang->action->label->started;
$lang->action->search->label['restarted'] = $lang->action->label->restarted;
$lang->action->search->label['recordestimate'] = $lang->action->label->recordestimate;
$lang->action->search->label['editestimate'] = $lang->action->label->editestimate;
$lang->action->search->label['canceled'] = $lang->action->label->canceled;
$lang->action->search->label['finished'] = $lang->action->label->finished;
$lang->action->search->label['paused'] = $lang->action->label->paused;
$lang->action->search->label['verified'] = $lang->action->label->verified;
$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, 由 <strong>$actor</strong> 创建子目录 <strong>$extra</strong>。' . "\n";
$lang->action->desc->linkchildstory = '$date, 由 <strong>$actor</strong> 关联子目录 <strong>$extra</strong>。' . "\n";
$lang->action->desc->unlinkchildrenstory = '$date, 由 <strong>$actor</strong> 移除子目录 <strong>$extra</strong>。' . "\n";
$lang->action->desc->linkparentstory = '$date, 由 <strong>$actor</strong> 关联到父目录 <strong>$extra</strong>。' . "\n";
$lang->action->desc->unlinkparentstory = '$date, 由 <strong>$actor</strong> 从父目录<strong>$extra</strong>取消关联。' . "\n";
$lang->action->desc->deletechildrenstory = '$date, 由 <strong>$actor</strong> 删除子目录<strong>$extra</strong>。' . "\n";
@@ -0,0 +1,3 @@
<script>
$('#zentaoLinks > .row > .col-sm-2').removeClass('col-sm-2').addClass('col-sm-4');
</script>
+2
View File
@@ -0,0 +1,2 @@
<?php
$config->block->closed = '|html,|contribute';
@@ -0,0 +1,58 @@
<?php
helper::importControl('block');
class myBlock extends block
{
/**
* Welcome block.
*
* @access public
* @return void
*/
public function welcome()
{
$this->view->tutorialed = $this->loadModel('tutorial')->getTutorialed();
$tasks = $this->dao->select('t1.id,t1.status,t1.deadline,t1.estStarted,t2.begin,t2.end')->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('t1.status')->in('wait,doing')
->andWhere('(t2.status')->ne('suspended')
->orWhere('t3.status')->ne('suspended')
->markRight(1)
->andWhere('t1.deleted')->eq('0')
->beginIF($this->config->systemMode == 'new')->andWhere('t2.deleted')->eq('0')->fi()
->andWhere('t3.deleted')->eq('0')
->andWhere('t1.vision')->eq($this->config->vision)
->fetchAll('id');
$today = helper::today();
$todayTimeStamp = strtotime($today);
$threeDayTimeStamp = $todayTimeStamp + (86400 * 3);
$data = array();
$data['undone'] = count($tasks);
$data['delaying'] = 0;
$data['delayed'] = 0;
foreach($tasks as $key => $task)
{
if(helper::isZeroDate($task->deadline)) $task->deadline = $task->end;
if(helper::isZeroDate($task->estStarted)) $task->estStarted = $task->begin;
$endTimeStamp = strtotime($task->deadline);
if($endTimeStamp < $todayTimeStamp) $data['delayed'] += 1;
if($endTimeStamp > $todayTimeStamp and $endTimeStamp < $threeDayTimeStamp) $data['delaying'] += 1;
}
$this->view->data = $data;
$time = date('H:i');
$welcomeType = '19:00';
foreach($this->lang->block->welcomeList as $type => $name)
{
if($time >= $type) $welcomeType = $type;
}
$this->view->welcomeType = $welcomeType;
$this->display();
}
}
@@ -0,0 +1,50 @@
<?php
$lang->block->flowchart = array();
$lang->block->flowchart['admin'] = array('管理员', '维护公司', '添加用户', '维护权限');
$lang->block->flowchart['project'] = array('项目负责人', '创建项目', '维护团队', "维护目标", '创建看板');
$lang->block->flowchart['dev'] = array('执行人员', '创建任务', '认领任务', '执行任务');
$lang->block->undone = '未完成';
$lang->block->delaying = '即将到期';
$lang->block->delayed = '已延期';
$lang->block->titleList['scrumlist'] = '看板列表';
$lang->block->titleList['sprint'] = '看板总览';
$lang->block->myTask = '我的任务';
$lang->block->finishedTasks = '完成的任务数';
$lang->block->story = '目标';
$lang->block->storyCount = '目标数';
unset($lang->block->default['full']['my']['9']);
$lang->block->default['full']['my']['5']['title'] = '看板列表';
$lang->block->default['full']['my']['5']['block'] = 'scrumlist';
$lang->block->default['full']['my']['5']['source'] = 'execution';
$lang->block->default['full']['my']['5']['params']['type'] = 'doing';
$lang->block->default['full']['my']['5']['params']['orderBy'] = 'id_desc';
$lang->block->default['full']['my']['5']['params']['count'] = '15';
$lang->block->modules['kanban']['index'] = new stdclass();
$lang->block->modules['kanban']['index']->availableBlocks = new stdclass();
$lang->block->modules['kanban']['index']->availableBlocks->scrumoverview = '项目概况';
$lang->block->modules['kanban']['index']->availableBlocks->scrumlist = $lang->executionCommon . '列表';
$lang->block->modules['kanban']['index']->availableBlocks->sprint = $lang->executionCommon . '总览';
$lang->block->modules['kanban']['index']->availableBlocks->projectdynamic = '最新动态';
$lang->block->modules['project']->availableBlocks = new stdclass();
$lang->block->modules['project']->availableBlocks->project = '项目列表';
$lang->block->modules['execution'] = new stdclass();
$lang->block->modules['execution']->availableBlocks = new stdclass();
$lang->block->modules['execution']->availableBlocks->statistic = $lang->execution->common . '统计';
$lang->block->modules['execution']->availableBlocks->overview = $lang->execution->common . '总览';
$lang->block->modules['execution']->availableBlocks->list = $lang->execution->common . '列表';
$lang->block->modules['execution']->availableBlocks->task = '任务列表';
unset($lang->block->moduleList['product']);
unset($lang->block->moduleList['qa']);
@@ -0,0 +1,10 @@
<script>
$('.block-project table > thead > tr > th:last-child').remove();
$('.block-project table > tbody > tr > td:last-child').remove();
$('.block-scrumtest').remove();
</script>
<?php if($code == 'list' && $module == 'todo'):?>
<script>
$('form[action*="todo"] button.btn-primary').parent().append('<input type="hidden" name="vision" id="vision" value="lite">');
</script>
<?php endif;?>
@@ -0,0 +1,3 @@
<script>
$('#assigntomeBlock>ul>li>a:not([href$="todo"]):not([href$="task"])').parent().remove();
</script>
@@ -0,0 +1,46 @@
<?php
/**
* The welcome view file of block module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package block
* @version $Id$
* @link http://www.zentao.net
*/
?>
<style>
.block-welcome .col-right > h4 {font-weight: normal;}
.block-welcome .col-right > h4 small {display: inline-block;margin-right: 8px;font-size: 14px;}
.block-welcome .col-right .tile {width: 33%;}
.block-welcome .panel-body {padding-top: 15px;}
.block-welcome .user-notification-icon {position: relative;display: inline-block;margin-left: 5px;}
.block-welcome .user-notification-icon .label-badge {position: absolute;top: 1px;right: -8px;min-width: 16px;padding: 2px;font-size: 12px;font-weight: normal;}
.block-welcome.block-sm .col-right {padding: 0;}
.block-welcome.block-sm .col-right .tiles {border-left: none; padding-left: 0}
.block-welcome.block-sm .tile-title {font-size: 12px; margin: 0 -10px;}
.block-welcome .progress-group{margin-top: 20px;}
.block-welcome .progress{margin-top: 10px; width: 85%}
</style>
<div class="panel-body conatiner-fluid">
<div class="table-row">
<div class="col col-right">
<h4><small class="text-muted"><?php echo date(DT_DATE3)?></small> <?php echo $lang->block->leftToday?></h4>
<div class="row tiles">
<div class="col tile">
<div class="tile-title"><?php echo $lang->block->undone?></div>
<div class="tile-amount"><?php echo empty($data) ? 0 : html::a($this->createLink('my', 'work', 'mode=task'), (int)$data['undone']);?></div>
</div>
<div class="col tile">
<div class="tile-title"><?php echo $lang->block->delaying?></div>
<div class="tile-amount"><?php echo empty($data) ? 0 : html::a($this->createLink('my', 'work', 'mode=task'), (int)$data['delaying']);?></div>
</div>
<div class="col tile">
<div class="tile-title"><?php echo $lang->block->delayed?></div>
<div class="tile-amount"><?php echo empty($data) ? 0 : html::a($this->createLink('my', 'work', 'mode=task'), (int)$data['delayed']);?></div>
</div>
</div>
</div>
</div>
</div>
@@ -0,0 +1,257 @@
<?php
$lang->execution->common = '看板';
$lang->executionCommon = '看板';
$lang->task->common = '任务';
$lang->story->common = '目标';
/* Main Navigation. */
$lang->mainNav = new stdclass();
$lang->mainNav->my = "{$lang->navIcons['my']} {$lang->my->shortCommon}|my|index|";
$lang->mainNav->project = "{$lang->navIcons['project']} {$lang->project->common}|$projectModule|$projectMethod|";
$lang->mainNav->execution = "{$lang->navIcons['execution']} 任务|$executionModule|$executionMethod|";
$lang->mainNav->kanban = "{$lang->navIcons['kanban']} {$lang->kanban->common}|kanban|space|";
$lang->mainNav->doc = "{$lang->navIcons['doc']} {$lang->doc->common}|doc|index|";
$lang->mainNav->system = "{$lang->navIcons['system']} {$lang->system->common}|my|team|";
$lang->mainNav->admin = "{$lang->navIcons['admin']} {$lang->admin->common}|admin|index|";
if($config->edition != 'open')
{
$lang->navIcons['feedback'] = "<i class='icon icon-feedback'></i>";
$lang->navIcons['oa'] = "<i class='icon icon-oa'></i>";
$lang->navIcons['workflow'] = "<i class='icon icon-flow'></i>";
$lang->mainNav->feedback = $lang->navIcons['feedback'] . '反馈|feedback|browse|';
$lang->mainNav->oa = $lang->navIcons['oa'] . '办公|attend|personal|';
$lang->mainNav->workflow = $lang->navIcons['workflow'] . '工作流|workflow|browseFlow|';
if($config->visions == ',lite,') unset($lang->mainNav->feedback);
}
/* Menu order. */
$lang->mainNav->menuOrder = array();
$lang->mainNav->menuOrder[5] = 'my';
$lang->mainNav->menuOrder[20] = 'project';
$lang->mainNav->menuOrder[30] = 'kanban';
$lang->mainNav->menuOrder[35] = 'doc';
$lang->mainNav->menuOrder[45] = 'system';
$lang->mainNav->menuOrder[65] = 'admin';
if($config->edition != 'open')
{
$lang->mainNav->menuOrder[21] = 'oa';
$lang->mainNav->menuOrder[25] = 'feedback';
$lang->mainNav->menuOrder[60] = 'workflow';
$lang->dividerMenu = ',oa,admin,';
if($config->visions == ',lite,') unset($lang->mainNav->menuOrder[25]);
}
else
{
$lang->dividerMenu = ',doc,admin,';
}
$lang->task->common = '任务';
/* My menu. */
$lang->my->menu = new stdclass();
$lang->my->menu->index = array('link' => "$lang->dashboard|my|index");
$lang->my->menu->calendar = array('link' => "$lang->calendar|my|calendar|", 'subModule' => 'todo', 'alias' => 'todo');
$lang->my->menu->task = array('link' => "{$lang->task->common}|my|contribute|mode=task&type=assignedTo", 'subModule' => 'task');
global $config;
if($config->edition != 'open') $lang->my->menu->effort = array('link' => '日志|effort|calendar|', 'exclude' => 'my-todo');
/* My menu order. */
$lang->my->menuOrder = array();
$lang->my->menuOrder[5] = 'index';
$lang->my->menuOrder[10] = 'calendar';
if($config->edition != 'open') $lang->my->menuOrder[11] = 'effort';
$lang->my->menuOrder[20] = 'task';
$lang->my->dividerMenu = ',calendar,';
$lang->project->target = '目标';
/* Scrum menu. */
$lang->kanban->menu = new stdclass();
$lang->kanban->menu->index = array('link' => "{$lang->dashboard}|project|index|project=%s");
$lang->kanban->menu->execution = array('link' => "$lang->executionKanban|project|execution|status=all&projectID=%s", 'subModule' => 'execution,task');
$lang->kanban->menu->story = array('link' => "{$lang->project->target}|projectstory|story|projectID=%s", 'subModule' => 'projectstory,tree,story', 'alias' => 'story,track');
$lang->kanban->menu->doc = array('link' => "{$lang->doc->common}|doc|tableContents|type=project&objectID=%s", 'subModule' => 'doc');
$lang->kanban->menu->dynamic = array('link' => "$lang->dynamic|project|dynamic|project=%s");
$lang->kanban->menu->settings = array('link' => "$lang->settings|project|view|project=%s", 'subModule' => 'stakeholder', 'alias' => 'edit,manageproducts,group,managemembers,manageview,managepriv,whitelist,addwhitelist,team');
$lang->kanban->dividerMenu = ',execution,settings,';
/* Scrum menu order. */
$lang->kanban->menuOrder = array();
$lang->kanban->menuOrder[5] = 'index';
$lang->kanban->menuOrder[10] = 'execution';
$lang->kanban->menuOrder[15] = 'story';
$lang->kanban->menuOrder[20] = 'doc';
$lang->kanban->menuOrder[25] = 'dynamic';
$lang->kanban->menuOrder[30] = 'settings';
$lang->execution->menu = new stdclass();
$lang->execution->menu->kanban = array('link' => "看板视图|execution|kanban|executionID=%s");
$lang->execution->menu->task = array('link' => "列表视图|execution|task|executionID=%s");
if($config->edition != 'open') $lang->execution->menu->calendar = array('link' => "日历视图|execution|calendar|executionID=%s");
if($config->edition != 'open') $lang->execution->menu->gantt = array('link' => "甘特图|execution|gantt|executionID=%s");
$lang->execution->menu->tree = array('link' => "树状图|execution|tree|executionID=%s");
$lang->execution->menu->grouptask = array('link' => "分组视图|execution|grouptask|executionID=%s");
$lang->kanban->menu->doc['subMenu'] = new stdclass();
$lang->kanban->menu->settings['subMenu'] = new stdclass();
$lang->kanban->menu->settings['subMenu']->view = array('link' => "$lang->overview|project|view|project=%s", 'alias' => 'edit');
$lang->kanban->menu->settings['subMenu']->members = array('link' => "{$lang->team->common}|project|team|project=%s", 'alias' => 'managemembers,team');
$lang->kanban->menu->settings['subMenu']->whitelist = array('link' => "{$lang->whitelist}|project|whitelist|project=%s", 'subModule' => 'personnel');
unset($lang->doc->menu->product);
unset($lang->doc->menu->api);
unset($lang->doc->menu->execution);
$lang->URCommon = '目标';
$lang->SRCommon = '目标';
/* Doc menu. */
$lang->doc->menu = new stdclass();
$lang->doc->menu->dashboard = array('link' => "{$lang->dashboard}|doc|index");
$lang->doc->menu->recent = array('link' => "{$lang->doc->recent}|doc|browse|browseTyp=byediteddate", 'alias' => 'recent');
$lang->doc->menu->my = array('link' => "{$lang->doc->my}|doc|browse|browseTyp=openedbyme", 'alias' => 'my');
$lang->doc->menu->collect = array('link' => "{$lang->doc->favorite}|doc|browse|browseTyp=collectedbyme", 'alias' => 'collect');
$lang->doc->menu->project = array('link' => "{$lang->doc->project}|doc|tableContents|type=project", 'alias' => 'showfiles,project');
$lang->doc->menu->custom = array('link' => "{$lang->doc->custom}|doc|tableContents|type=custom", 'alias' => 'custom');
$lang->doc->dividerMenu = ',project,';
/* Doc menu order. */
$lang->doc->menuOrder = array();
$lang->doc->menuOrder[5] = 'dashboard';
$lang->doc->menuOrder[10] = 'recent';
$lang->doc->menuOrder[15] = 'my';
$lang->doc->menuOrder[20] = 'collect';
$lang->doc->menuOrder[25] = 'project';
$lang->doc->menuOrder[30] = 'custom';
$lang->doc->menu->project['subMenu'] = new stdclass();
$lang->doc->menu->custom['subMenu'] = new stdclass();
/* Admin menu. */
$lang->admin->menu = new stdclass();
$lang->admin->menu->index = array('link' => "$lang->indexPage|admin|index", 'alias' => 'register,certifytemail,certifyztmobile,ztcompany');
$lang->admin->menu->company = array('link' => "{$lang->personnel->common}|company|browse|", 'subModule' => ',user,dept,group,');
$lang->admin->menu->custom = array('link' => "{$lang->custom->common}|custom|index", 'exclude' => 'custom-browsestoryconcept,custom-timezone,custom-estimate');
$lang->admin->menu->extension = array('link' => "{$lang->extension->common}|extension|browse", 'subModule' => 'extension');
$lang->admin->menu->dev = array('link' => "$lang->redev|dev|api", 'alias' => 'db', 'subModule' => 'dev,editor,entry');
$lang->admin->menu->message = array('link' => "{$lang->message->common}|message|index", 'subModule' => 'message,mail,webhook,sms');
$lang->admin->menu->system = array('link' => "{$lang->admin->system}|backup|index", 'subModule' => 'cron,backup,action,admin,search,ldap', 'exclude' => 'admin-index,admin-xuanxuan,admin-register,admin-ztcompany');
/* Admin menu order. */
$lang->admin->menuOrder = array();
$lang->admin->menuOrder[5] = 'index';
$lang->admin->menuOrder[10] = 'company';
$lang->admin->menuOrder[15] = 'custom';
$lang->admin->menuOrder[20] = 'message';
$lang->admin->menuOrder[25] = 'extension';
$lang->admin->menuOrder[30] = 'dev';
$lang->admin->menuOrder[35] = 'system';
$lang->admin->menu->message['subMenu'] = new stdclass();
$lang->admin->menu->message['subMenu']->message = new stdclass();
$lang->admin->menu->message['subMenu']->mail = array('link' => "{$lang->mail->common}|mail|index", 'subModule' => 'mail');
$lang->admin->menu->message['subMenu']->webhook = array('link' => "Webhook|webhook|browse", 'subModule' => 'webhook');
if($config->edition != 'open') $lang->admin->menu->message['subMenu']->sms = array('link' => "短信|sms|index");
$lang->admin->menu->message['subMenu']->browser = array('link' => "$lang->browser|message|browser");
$lang->admin->menu->message['subMenu']->setting = array('link' => "$lang->settings|message|setting");
$lang->admin->menu->message['menuOrder'][5] = 'mail';
$lang->admin->menu->message['menuOrder'][10] = 'webhook';
$lang->admin->menu->message['menuOrder'][11] = 'sms';
$lang->admin->menu->message['menuOrder'][15] = 'browser';
$lang->admin->menu->message['menuOrder'][20] = 'setting';
$lang->admin->menu->company['subMenu'] = new stdclass();
$lang->admin->menu->company['subMenu']->browseUser = array('link' => "{$lang->user->common}|company|browse", 'subModule' => 'user');
$lang->admin->menu->company['subMenu']->dept = array('link' => "{$lang->dept->common}|dept|browse", 'subModule' => 'dept');
$lang->admin->menu->company['subMenu']->browseGroup = array('link' => "{$lang->priv}|group|browse", 'subModule' => 'group');
$lang->admin->menu->dev['subMenu'] = new stdclass();
$lang->admin->menu->dev['subMenu']->api = array('link' => "API|dev|api");
$lang->admin->menu->dev['subMenu']->db = array('link' => "$lang->db|dev|db");
$lang->admin->menu->dev['subMenu']->editor = array('link' => "$lang->editor|dev|editor");
$lang->admin->menu->dev['subMenu']->entry = array('link' => "{$lang->admin->entry}|entry|browse", 'subModule' => 'entry');
$lang->admin->menu->dev['menuOrder'][5] = 'api';
$lang->admin->menu->dev['menuOrder'][10] = 'db';
$lang->admin->menu->dev['menuOrder'][15] = 'editor';
$lang->admin->menu->dev['menuOrder'][20] = 'entry';
$lang->admin->menu->system['subMenu'] = new stdclass();
$lang->admin->menu->system['subMenu']->data = array('link' => "{$lang->admin->data}|backup|index", 'subModule' => 'action');
$lang->admin->menu->system['subMenu']->safe = array('link' => "$lang->security|admin|safe", 'alias' => 'checkweak');
$lang->admin->menu->system['subMenu']->cron = array('link' => "{$lang->admin->cron}|cron|index", 'subModule' => 'cron');
$lang->admin->menu->system['subMenu']->timezone = array('link' => "$lang->timezone|custom|timezone");
$lang->admin->menu->system['subMenu']->buildIndex = array('link' => "{$lang->admin->buildIndex}|search|buildindex|");
if($config->edition != 'open')
{
$lang->admin->menu->system['subMenu']->ldap = array('link' => 'LDAP|ldap|set', 'subModule' => 'ldap');
$lang->admin->menu->system['subMenu']->libreoffice = array('link' => 'Office|custom|libreoffice');
}
$lang->admin->dividerMenu = ',company,message,system,';
/* adjust items of search. */
$lang->searchObjects['all'] = '全部';
$lang->searchObjects['todo'] = '待办';
$lang->searchObjects['story'] = '目标';
$lang->searchObjects['task'] = '任务';
$lang->searchObjects['doc'] = '文档';
$lang->searchObjects['project'] = '项目';
$lang->searchObjects['execution'] = '看板';
if($config->edition != 'open') $lang->searchObjects['feedback'] = '反馈';
if($config->visions == ',lite,') unset($lang->searchObjects['feedback']);
$lang->navGroup->task = 'project';
$lang->navGroup->execution = 'project';
unset($lang->searchObjects['bug']);
unset($lang->searchObjects['testcase']);
unset($lang->searchObjects['product']);
unset($lang->searchObjects['build']);
unset($lang->searchObjects['release']);
unset($lang->searchObjects['productplan']);
unset($lang->searchObjects['testtask']);
unset($lang->searchObjects['caselib']);
unset($lang->searchObjects['testreport']);
unset($lang->searchObjects['program']);
unset($lang->searchObjects['user']);
/* biz search. */
unset($lang->searchObjects['service']);
unset($lang->searchObjects['deploy']);
unset($lang->searchObjects['deploystep']);
/* max search. */
unset($lang->searchObjects['trainplan']);
unset($lang->searchObjects['risk']);
unset($lang->searchObjects['issue']);
unset($lang->searchObjects['opportunity']);
/* adjust items of global create. */
unset($lang->createIcons['effort']);
unset($lang->createIcons['bug']);
unset($lang->createIcons['testcase']);
unset($lang->createIcons['product']);
unset($lang->createIcons['program']);
$lang->createObjects['story'] = '目标';
$lang->createObjects['task'] = '任务';
$lang->createObjects['execution'] = '任务看板';
$lang->createObjects['kanban'] = '通用看板';
$lang->createIcons['execution'] = 'kanban';
@@ -0,0 +1,4 @@
<script>
$('#userNav li:first ul.dropdown-menu li a[href*="tutorial"]').parent().remove();
$('#userNav li:first ul.dropdown-menu li a[href*="preference"]').parent().remove();
</script>
@@ -0,0 +1,3 @@
<?php
$lang->company->execution = '看板';
$lang->company->product = '项目';
+12
View File
@@ -0,0 +1,12 @@
<?php
$config->custom->requiredModules = array();
$config->custom->requiredModules[10] = 'project';
$config->custom->requiredModules[20] = 'story';
$config->custom->requiredModules[35] = 'execution';
$config->custom->requiredModules[40] = 'task';
$config->custom->requiredModules[80] = 'doc';
$config->custom->requiredModules[85] = 'user';
$config->custom->fieldList['execution']['create'] = 'desc';
$config->custom->fieldList['execution']['edit'] = 'desc,PO,PM,QD,RD';
$config->custom->fieldList['story']['create'] = 'module,pri,estimate,keywords';
@@ -0,0 +1,28 @@
<?php
$lang->custom->execution = '看板';
$lang->custom->closedExecution = '已关闭' . $lang->custom->execution;
$lang->custom->notice->readOnlyOfExecution = "禁止修改后,已关闭{$lang->custom->execution}下的任务、日志以及关联目标都禁止修改。";
$lang->custom->moduleName['execution'] = $lang->custom->execution;
$lang->custom->object = array();
$lang->custom->object['project'] = '项目';
$lang->custom->object['execution'] = $lang->custom->execution;
$lang->custom->object['story'] = $lang->SRCommon;
$lang->custom->object['task'] = '任务';
$lang->custom->object['todo'] = '待办';
$lang->custom->object['user'] = '用户';
$lang->custom->object['block'] = '区块';
$lang->custom->task = new stdClass();
$lang->custom->task->fields['priList'] = '优先级';
$lang->custom->story = new stdClass();
$lang->custom->story->fields['priList'] = '优先级';
$lang->custom->story->fields['reasonList'] = '关闭原因';
$lang->custom->story->fields['statusList'] = '状态';
$lang->custom->story->fields['reviewRules'] = '评审规则';
$lang->custom->story->fields['reviewResultList'] = '评审结果';
$lang->custom->story->fields['review'] = '评审流程';
if($this->config->edition != 'open') $lang->custom->system = array('required', 'score');
@@ -0,0 +1,36 @@
<?php
/**
* Get field list.
*
* @param string $module
* @access public
* @return array
*/
public function getFieldList($module)
{
if(!isset($this->config->$module)) $this->loadModel($module);
if($this->session->currentProductType === 'normal') unset($this->config->$module->datatable->fieldList['branch']);
foreach($this->config->$module->datatable->fieldList as $field => $items)
{
if($field === 'branch')
{
if($this->session->currentProductType === 'branch') $this->config->$module->datatable->fieldList[$field]['title'] = $this->lang->datatable->branch; if($this->session->currentProductType === 'platform') $this->config->$module->datatable->fieldList[$field]['title'] = $this->lang->datatable->platform;
continue; }
$title = zget($this->lang->$module, $items['title'], zget($this->lang, $items['title'], $items['title']));
$this->config->$module->datatable->fieldList[$field]['title'] = $title;
}
if($this->config->edition != 'open' and $module != 'story')
{
$fields = $this->loadModel('workflowfield')->getList($module);
foreach($fields as $field)
{
if($field->buildin) continue;
$this->config->$module->datatable->fieldList[$field->field]['title'] = $field->name;
$this->config->$module->datatable->fieldList[$field->field]['width'] = '120';
$this->config->$module->datatable->fieldList[$field->field]['fixed'] = 'no';
$this->config->$module->datatable->fieldList[$field->field]['required'] = 'no';
}
}
return $this->config->$module->datatable->fieldList;
}
+63
View File
@@ -0,0 +1,63 @@
<?php
$config->dev->group = array();
$config->dev->group['index'] = 'my';
$config->dev->group['my'] = 'my';
$config->dev->group['todo'] = 'my';
$config->dev->group['program'] = 'program';
$config->dev->group['story'] = 'project';
$config->dev->group['storyspec'] = 'project';
$config->dev->group['storystage'] = 'project';
$config->dev->group['project'] = 'project';
$config->dev->group['projectproduct'] = 'project';
$config->dev->group['projectstory'] = 'project';
$config->dev->group['execution'] = 'execution';
$config->dev->group['task'] = 'execution';
$config->dev->group['taskestimate'] = 'execution';
$config->dev->group['team'] = 'execution';
$config->dev->group['burn'] = 'execution';
$config->dev->group['doc'] = 'doc';
$config->dev->group['doccontent'] = 'doc';
$config->dev->group['doclib'] = 'doc';
$config->dev->group['report'] = 'report';
$config->dev->group['datatable'] = 'report';
$config->dev->group['company'] = 'company';
$config->dev->group['dept'] = 'company';
$config->dev->group['group'] = 'company';
$config->dev->group['grouppriv'] = 'company';
$config->dev->group['user'] = 'company';
$config->dev->group['usercontact'] = 'company';
$config->dev->group['usergroup'] = 'company';
$config->dev->group['userquery'] = 'company';
$config->dev->group['usertpl'] = 'company';
$config->dev->group['userview'] = 'company';
$config->dev->group['admin'] = 'admin';
$config->dev->group['extension'] = 'admin';
$config->dev->group['lang'] = 'admin';
$config->dev->group['convert'] = 'admin';
$config->dev->group['action'] = 'admin';
$config->dev->group['history'] = 'admin';
$config->dev->group['mail'] = 'admin';
$config->dev->group['backup'] = 'admin';
$config->dev->group['cron'] = 'admin';
$config->dev->group['dev'] = 'admin';
$config->dev->group['custom'] = 'admin';
$config->dev->group['score'] = 'admin';
$config->dev->group['config'] = 'admin';
$config->dev->group['api'] = 'api';
$config->dev->group['entry'] = 'api';
$config->dev->group['log'] = 'api';
$config->dev->group['install'] = 'system';
$config->dev->group['upgrade'] = 'system';
$config->dev->group['sso'] = 'system';
$config->dev->group['search'] = 'system';
$config->dev->group['block'] = 'system';
$config->dev->group['file'] = 'system';
$config->dev->group['tree'] = 'system';
$config->dev->group['module'] = 'system';
$config->dev->group['tutorial'] = 'system';
$config->dev->group['message'] = 'message';
$config->dev->group['mail'] = 'message';
$config->dev->group['webhook'] = 'message';
$config->dev->group['notify'] = 'message';
$config->dev->group['searchindex'] = 'search';
$config->dev->group['searchdict'] = 'search';
@@ -0,0 +1,87 @@
<?php
$lang->dev->tableList = array();
$lang->dev->tableList['action'] = '系统日志';
$lang->dev->tableList['burn'] = '燃尽图';
$lang->dev->tableList['company'] = '公司';
$lang->dev->tableList['config'] = '配置';
$lang->dev->tableList['custom'] = '自定义';
$lang->dev->tableList['dept'] = '部门';
$lang->dev->tableList['doc'] = '文档';
$lang->dev->tableList['doclib'] = '文档库';
$lang->dev->tableList['effort'] = '日志';
$lang->dev->tableList['extension'] = '插件';
$lang->dev->tableList['file'] = '附件';
$lang->dev->tableList['group'] = '用户组';
$lang->dev->tableList['grouppriv'] = '组权限';
$lang->dev->tableList['history'] = '操作历史';
$lang->dev->tableList['lang'] = '语言定义';
$lang->dev->tableList['module'] = '模块';
$lang->dev->tableList['project'] = '项目';
$lang->dev->tableList['projectproduct'] = '项目' . $lang->productCommon;
$lang->dev->tableList['projectstory'] = '项目' . $lang->SRCommon;
$lang->dev->tableList['execution'] = $lang->executionCommon;
$lang->dev->tableList['story'] = $lang->SRCommon;
$lang->dev->tableList['storyspec'] = "{$lang->SRCommon}描述";
$lang->dev->tableList['task'] = '任务';
$lang->dev->tableList['taskestimate'] = '任务预计';
$lang->dev->tableList['team'] = '团队';
$lang->dev->tableList['todo'] = '待办';
$lang->dev->tableList['user'] = '用户';
$lang->dev->tableList['usercontact'] = '用户联系人';
$lang->dev->tableList['usergroup'] = '用户组';
$lang->dev->tableList['userquery'] = '用户查询';
$lang->dev->tableList['usertpl'] = '用户模板';
$lang->dev->tableList['admin'] = '后台管理';
$lang->dev->tableList['api'] = 'API接口';
$lang->dev->tableList['backup'] = '备份';
$lang->dev->tableList['common'] = '公有模块';
$lang->dev->tableList['convert'] = '导入';
$lang->dev->tableList['dev'] = '二次开发';
$lang->dev->tableList['index'] = '首页';
$lang->dev->tableList['install'] = '安装';
$lang->dev->tableList['mail'] = '邮箱';
$lang->dev->tableList['misc'] = '杂项';
$lang->dev->tableList['my'] = '我的地盘';
$lang->dev->tableList['qa'] = '测试';
$lang->dev->tableList['report'] = '统计';
$lang->dev->tableList['search'] = '搜索';
$lang->dev->tableList['sso'] = '单点登录';
$lang->dev->tableList['tree'] = '模块关系';
$lang->dev->tableList['upgrade'] = '更新';
$lang->dev->tableList['cron'] = '定时任务';
$lang->dev->tableList['datatable'] = '数据表格';
$lang->dev->tableList['block'] = '区块';
$lang->dev->tableList['branch'] = '平台/分支';
$lang->dev->tableList['doccontent'] = '文档内容';
$lang->dev->tableList['storystage'] = "{$lang->SRCommon}阶段";
$lang->dev->tableList['tutorial'] = '新手教程';
$lang->dev->tableList['score'] = '积分';
$lang->dev->tableList['entry'] = '应用';
$lang->dev->tableList['webhook'] = 'WebHook';
$lang->dev->tableList['log'] = '接口日志';
$lang->dev->tableList['message'] = '消息';
$lang->dev->tableList['notify'] = '通知';
$lang->dev->tableList['userview'] = '可访问权限';
$lang->dev->tableList['searchdict'] = '搜索字典';
$lang->dev->tableList['searchindex'] = '搜索索引';
$lang->dev->tableList['kanbanlane'] = '看板泳道';
$lang->dev->tableList['kanbancolumn'] = '看板列';
$lang->dev->tableList['im_chat_message_index'] = 'im聊天消息';
$lang->dev->tableList['im_message_backup'] = 'im消息备份';
$lang->dev->tableList['im_message_index'] = 'im消息索引';
$lang->dev->tableList['im_userdevice'] = 'im用户设备';
$lang->dev->groupList = array();
$lang->dev->groupList['my'] = '我的地盘';
$lang->dev->groupList['project'] = '项目';
$lang->dev->groupList['execution'] = $lang->executionCommon;
$lang->dev->groupList['doc'] = '文档';
$lang->dev->groupList['report'] = '统计';
$lang->dev->groupList['company'] = '组织';
$lang->dev->groupList['api'] = 'API';
$lang->dev->groupList['message'] = '消息';
$lang->dev->groupList['search'] = '搜索';
$lang->dev->endGroupList['admin'] = '后台';
$lang->dev->endGroupList['system'] = '系统';
$lang->dev->endGroupList['other'] = '其他';
@@ -0,0 +1,4 @@
<?php
$lang->doc->libTypeList = array();
$lang->doc->libTypeList['project'] = '项目文档库';
$lang->doc->libTypeList['custom'] = '自定义文档库';
+13
View File
@@ -0,0 +1,13 @@
<?php
public function getLibIdListByProject($projectID = 0)
{
$executions = $this->loadModel('execution')->getPairs($projectID, 'all', 'noclosed');
$executionLibs = array();
if($executions) $executionLibs = $this->dao->select('id')->from(TABLE_DOCLIB)->where('execution')->in(array_keys($executions))->fetchPairs();
$productLibs = $this->dao->select('id')->from(TABLE_DOCLIB)->where('product')->eq('0')->fetchPairs();
$customLibs = $this->dao->select('id')->from(TABLE_DOCLIB)->where('type')->eq('custom')->fetchPairs();
$libIdList = array_merge($customLibs, $executionLibs, $productLibs);
return $libIdList;
}
@@ -0,0 +1,6 @@
<script>
$(function()
{
$('#submit').parent().append('<input type="hidden" name="vision" id="vision" value="lite">');
});
</script>
@@ -0,0 +1,6 @@
<script>
$(function()
{
$('#submit').parent().append('<input type="hidden" name="vision" id="vision" value="lite">');
});
</script>
@@ -0,0 +1,53 @@
<?php if($this->app->tab == 'project'):?>
<script>
$('#pageNav .btn-group #dropMenu .table-col .list-group a[href*="showFiles"]').remove();
$('#pageActions .btn-toolbar .btn-group:first').remove();
</script>
<?php endif;?>
<?php if($this->app->tab == 'doc'):?>
<script>
$('#pageNav .btn-group #dropMenu .table-col .list-group a[href*="showFiles"]').remove();
</script>
<?php endif;?>
<?php if(!empty($doc) and !$doc->deleted and $doc->version > 1 and common::hasPriv('doc', 'diff')):?>
<?php
$versions = array();
$i = 1;
foreach($actions as $action)
{
if($action->action == 'created' or $action->action == 'deletedfile' or $action->action == 'commented')
{
$versions[$i] = "#$i " . zget($users, $action->actor) . ' ' . substr($action->date, 2, 14);
$i++;
}
elseif($action->action == 'edited')
{
foreach($action->history as $history)
{
if($history->field == 'content')
{
$versions[$i] = "#$i " . zget($users, $action->actor) . ' ' . substr($action->date, 2, 14);
$i++;
break;
}
}
}
}
krsort($versions);
$diffHtml = "<div class='btn-group versions'>";
$diffHtml .= "<button data-toggle='dropdown' type='button' class='btn btn-link dropdown-toggle'>{$lang->doc->diff} <span class='caret'></span></button>";
$diffHtml .= "<ul class='dropdown-menu pull-right'>";
foreach($versions as $i => $versionTitle)
{
if($i == $doc->version) continue;
$diffHtml .= '<li>' . html::a(inlink('diff', "docID=$doc->id&newVersion=$doc->version&version=$i"), $versionTitle) . '</li>';
}
$diffHtml .= "</ul>";
$diffHtml .= "</div>";
?>
<script>
$('#mainContent #content .detail-title .actions').append(<?php echo json_encode($diffHtml)?>);
</script>
<?php endif;?>
@@ -0,0 +1 @@
<?php include dirname(__FILE__) . '/objectlibs.lite.html.hook.php';?>
@@ -0,0 +1,210 @@
<?php
/**
* The view file of calendar module of ZenTaoPMS.
*
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
* @license business(商业软件)
* @author Yangyang Shi <shiyangyang@cnezsoft.com>
* @package calendar
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<?php include $app->getModuleRoot() . 'common/view/datepicker.html.php';?>
<?php include $app->getExtensionRoot() . 'biz/common/ext/view/calendar.html.php';?>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
<?php if(common::hasPriv('my', 'todo')) echo html::a(helper::createLink('my', 'todo', "type=all"), $lang->todo->all . " <span class='label label-light label-badge'>{$todoCount}</span>", '', "class='btn btn-link'");?>
<?php if(isset($effortCount)):?>
<?php if(common::hasPriv('my', 'effort')) echo html::a(helper::createLink('my', 'effort', "type=all"), $lang->effort->all . " <span class='label label-light label-badge'>{$effortCount}</span>", '', "class='btn btn-link'");?>
<?php endif?>
</div>
<div class="btn-toolbar pull-right">
<?php if(common::hasPriv('effort', 'export')) echo html::a('javascript:exportCalendar("' . helper::createLink('effort', 'export', "userID={$user->id}&orderBy=date_asc&date=_date_") . '")', "<i class='icon-export muted'> </i> " . $lang->effort->export, '', "class='btn btn-link'") ?>
<?php
$date = str_replace('-', '', $date);
common::printLink('effort', 'batchCreate', "date=$date", "<i class='icon icon-plus'></i> " . $lang->effort->create, '', "class='btn btn-primary' id='batchCreate'", '', true);
?>
</div>
</div>
<div class="main-row">
<div class="main-col">
<div class="cell">
<div id="effortCalendar" class="calendar">
<header class="calender-header table-row">
<div class="btn-toolbar col-4 table-col text-middle">
<button type="button" class="btn btn-info btn-icon btn-mini btn-prev"><i class="icon-chevron-left"></i></button>
<button type="button" class="btn btn-info btn-mini btn-today"><?php echo $lang->today;?></button>
<button type="button" class="btn btn-info btn-icon btn-mini btn-next"><i class="icon-chevron-right"></i></button>
<span class="calendar-caption"></span>
</div>
<div class="col-4 text-center table-col">
<ul class="nav nav-primary">
<?php if(common::hasPriv('todo', 'calendar')):?>
<li><?php echo html::a($this->createLink('todo', 'calendar'), $lang->todo->common);?></li>
<?php elseif(common::hasPriv('my', 'todo')):?>
<li><?php echo html::a($this->createLink('my', 'todo'), $lang->todo->common);?></li>
<?php endif;?>
<li class="active"><?php echo html::a($this->createLink('effort', 'calendar'), $lang->effort->common);?></li>
</ul>
</div>
<div class="col-4 table-col"></div>
</header>
</div>
</div>
</div>
</div>
<script>
config.ajaxGetEffortsUrl = '<?php echo $this->createLink('effort', 'ajaxGetEfforts', "userID={$this->app->user->id}&year={year}");?>';
config.effortViewUrl = '<?php echo $this->createLink('effort', 'view', 'id={id}', '', true);?>';
config.batchAddUrl = '<?php echo $this->createLink('effort', 'batchCreate', 'date={date}', '', true);?>';
config.textNetworkError = '<?php echo $lang->textNetworkError;?>';
config.textHasMoreItems = '<?php echo $lang->textHasMoreItems;?>';
</script>
<script>
var effortViewModalTrigger = new $.zui.ModalTrigger(
{
width: '70%',
type: 'iframe',
rememberPos: 'effortViewModal',
waittime: 8000
});
var batchAddModalTrigger = new $.zui.ModalTrigger(
{
width: '95%',
type: 'iframe',
waittime: 8000,
});
var displayDate = 0;
var calendar = false;
$(function()
{
var expandedDays = {};
var minExpandCount = 6;
var $calendar = $('#effortCalendar');
var toggleLoading = function(loading)
{
$calendar.toggleClass('loading', !!loading);
};
calendar = $calendar.calendar(
{
dragThenDrop: false,
hideEmptyWeekends: true,
data:
{
events: [],
calendars:
{
defaultCal: {color: '#fff'}
}
},
beforeDisplay: function(display, doDisplay)
{
var date = display.date;
var thisDisplayDate = date.getFullYear();
if (displayDate === thisDisplayDate)
{
return doDisplay();
}
else
{
displayDate = thisDisplayDate;
}
var calendar = this;
toggleLoading(true);
$.ajax(
{
url: config.ajaxGetEffortsUrl.replace('{year}', date.getFullYear()),
dataType: 'json',
success: function(data)
{
$.each(data, function(index, effort)
{
effort.allDay = !effort.end;
});
calendar.resetData({events: data});
doDisplay();
},
error: function()
{
$.zui.messager.danger(config.textNetworkError);
},
complete: function() {toggleLoading(false);}
});
return false;
},
eventCreator: function(event, $cell, calendar)
{
var $event = $('<div title="' + event.title + '" data-id="' + (event.id || '') + '" class="event has-time" title="' + (event.desc || '') + '"><span class="title">' + event.title + '</span><span class="time">' + event.consumed + 'h</span></div>');
return $event;
},
dayFormater: function($cell, date, dayEvents, calendar)
{
if(dayEvents && dayEvents.maxPos >= minExpandCount)
{
var hideManyEvents = !expandedDays[date.toDateString()];
$cell.toggleClass('hide-many-events', hideManyEvents);
if(hideManyEvents)
{
var $cellContent = $cell.find('.day > .content');
var $showMore = $cellContent.find('.show-more-events');
if(!$showMore.length)
{
$showMore = $('<div class="show-more-events" />').appendTo($cellContent);
}
else
{
$showMore.show();
}
$showMore.text(config.textHasMoreItems.format(dayEvents.maxPos - minExpandCount + 1));
}
}
else
{
$cell.removeClass('hide-many-events');
}
if($cell.is('.past,.current')) $cell.addClass('with-plus-sign');
},
eventSorter: function(a, b)
{
var result = a.start - b.start;
if (result === 0) {
return a.id - b.id;
}
return result;
}
}).data('zui.calendar');
$calendar.on('click', '.show-more-events', function(e)
{
var $cell = $(this).hide().closest('.cell-day');
$cell.removeClass('hide-many-events');
expandedDays[$cell.find('.day').attr('data-date')] = true;
e.stopPropagation();
}).on('click', '.event', function(e)
{
var event = $(this).data('event');
eventUrl = config.effortViewUrl.replace('{id}', event.id);
effortViewModalTrigger.show({url: eventUrl});
e.stopPropagation();
}).on('click', '.day', function(e)
{
var $day = $(this);
var $cell = $day.parent();
if (!$cell.hasClass('future') || $cell.hasClass('current'))
{
batchAddModalTrigger.show({url: config.batchAddUrl.replace('{date}', $day.data('date').format('yyyyMMdd')), showHeader:false});
}
e.stopPropagation();
});
$('#batchCreate').click(function(e)
{
batchAddModalTrigger.show({url: $(this).attr('href'), showHeader:false});
return false;
})
});
</script>
<?php include $app->getModuleRoot() . 'common/view/footer.html.php';?>
@@ -0,0 +1,76 @@
<?php
helper::importControl('execution');
class myExecution extends execution
{
public function kanban($executionID, $browseType = 'all', $orderBy = 'id_asc', $groupBy = 'default')
{
$this->app->loadLang('kanban');
common::setMenuVars('execution', $executionID);
$currentMethod = $this->app->methodName;
$execution = $this->execution->getById($executionID);
$this->loadModel('project')->setMenu($execution->project);
$this->lang->kanban->menu->execution['subMenu'] = new stdClass();
/* change subMenu to sub select menu */
$TRActions = $this->execution->getTRActions($currentMethod);
$TRActions .= "<div class='dropdown'>";
$TRActions .= html::a('javascript:;', $this->lang->execution->kanbanGroup[$groupBy] . "<span class='caret'></span>", '', "data-toggle='dropdown' data- class='btn btn-link'");
$TRActions .= "<ul class='dropdown-menu pull-right course-groupBy'>";
foreach($this->lang->execution->kanbanGroup as $groupKey => $groupName)
{
$attr = $groupBy == $groupKey ? '<i class="icon icon-check"></i>' : '';
$TRActions .= '<li>' . html::a(helper::createLink('execution', 'kanban', "execution=$execution->id&browseType=task&orderBy=$orderBy&groupBy=$groupKey"), $groupName . $attr) . '</li>';
}
$TRActions .= "</ul></div>";
$TRActions .= html::a('javascript:fullScreen()', "<i class='icon-fullscreen muted'></i> " . $this->lang->kanban->fullScreen, '', "class='btn btn-link'");
$printSettingBtn = (common::hasPriv('kanban', 'createRegion') or (common::hasPriv('kanban', 'setLaneHeight')) or common::hasPriv('execution', 'edit') or common::hasPriv('execution', 'close') or common::hasPriv('execution', 'delete') or !empty($executionActions));
$executionActions = array();
foreach($this->config->execution->statusActions as $action)
{
if($this->execution->isClickable($execution, $action)) $executionActions[] = $action;
}
if($this->execution->isClickable($execution, 'delete')) $executionActions[] = 'delete';
if($printSettingBtn)
{
$TRActions .= "<div class='dropdown'>";
$TRActions .= html::a('javascript:;', "<i class='icon icon-cog-outline'></i>" . $this->lang->kanban->setting, '', "data-toggle='dropdown' data- class='btn btn-link'");
$TRActions .= "<ul id='kanbanActionMenu' class='dropdown-menu pull-right'>";
$width = $this->app->getClientLang() == 'en' ? '70%' : '60%';
if(common::hasPriv('kanban', 'createRegion')) $TRActions .= '<li>' . html::a(helper::createLink('kanban', 'createRegion', "kanbanID=$execution->id&from=execution", '', true), '<i class="icon icon-plus"></i>' . $this->lang->kanban->createRegion, '', "class='iframe btn btn-link text-left'") . '</li>';
if(common::hasPriv('kanban', 'setLaneHeight')) $TRActions .= '<li>' . html::a(helper::createLink('kanban', 'setLaneHeight', "kanbanID=$execution->id&from=execution", '', true), '<i class="icon icon-size-height"></i>' . $this->lang->kanban->laneHeight, '', "class='iframe btn btn-link text-left' data-width=$width") . '</li>';
$kanbanActions = '';
if(common::hasPriv('execution', 'edit')) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'edit', "executionID=$execution->id", '', true), '<i class="icon icon-edit"></i>' . $this->lang->kanban->edit, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('start', $executionActions)) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'start', "executionID=$execution->id", '', true), '<i class="icon icon-play"></i>' . $this->lang->execution->start, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('putoff', $executionActions)) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'putoff', "executionID=$execution->id", '', true), '<i class="icon icon-calendar"></i>' . $this->lang->execution->putoff, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('suspend', $executionActions)) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'suspend', "executionID=$execution->id", '', true), '<i class="icon icon-pause"></i>' . $this->lang->execution->suspend, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('close', $executionActions)) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'close', "executionID=$execution->id", '', true), '<i class="icon icon-off"></i>' . $this->lang->execution->close, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('activate', $executionActions)) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'activate', "executionID=$execution->id", '', true), '<i class="icon icon-magic"></i>' . $this->lang->execution->activate, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(common::hasPriv('execution', 'delete')) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'delete', "executionID=$execution->id"), '<i class="icon icon-trash"></i>' . $this->lang->delete, 'hiddenwin', "class='btn btn-link text-left'") . '</li>';
if($kanbanActions)
{
$TRActions .= ((common::hasPriv('kanban', 'createRegion') or common::hasPriv('kanban', 'setLaneHeight')) and (common::hasPriv('execution', 'edit') or common::hasPriv('execution', 'delete') or !empty($executionActions))) ? "<div class='divider'></div>" . $kanbanActions : $kanbanActions;
}
$TRActions .= "</ul></div>";
}
$canCreateTask = common::hasPriv('task', 'create');
$canBatchCreateTask = common::hasPriv('task', 'batchCreate');
if($canCreateTask or $canBatchCreateTask)
{
$TRActions .= "<div class='dropdown' id='createDropdown'>";
$TRActions .= "<button class='btn btn-primary' type='button' data-toggle='dropdown'><i class='icon icon-plus'></i> {$this->lang->create} <span class='caret'></span></button>";
$TRActions .= "<ul class='dropdown-menu pull-right'>";
if($canCreateTask) $TRActions .= '<li>' . html::a(helper::createLink('task', 'create', "execution=$execution->id", '', true), $this->lang->task->create, '', "class='iframe'") . '</li>';
if($canBatchCreateTask) $TRActions .= '<li>' . html::a(helper::createLink('task', 'batchCreate', "execution=$execution->id", '', true), $this->lang->execution->batchCreateTask, '', "class='iframe'") . '</li>';
$TRActions .= "</ul></div>";
}
$this->lang->TRActions = $TRActions;
$browseType = 'task';
parent::kanban($executionID, $browseType, $orderBy, $groupBy);
}
}
@@ -0,0 +1,24 @@
<?php
unset($lang->execution->featureBar['all']['undone']);
unset($lang->execution->featureBar['all']['wait']);
unset($lang->execution->featureBar['all']['suspended']);
$lang->execution->createKanban = '创建看板';
$lang->execution->noExecution = "暂时没有看板。";
$lang->execution->importTask = '转入任务';
$lang->execution->batchCreateTask = '批量创建任务';
$lang->execution->kanbanGroup['default'] = '默认方式';
$lang->execution->kanbanGroup['story'] = '目标';
$lang->execution->kanbanGroup['module'] = '所属目录';
$lang->execution->kanbanGroup['pri'] = '优先级';
$lang->execution->kanbanGroup['assignedTo'] = '指派人';
$lang->execution->icons['kanban'] = 'kanban';
$lang->execution->icons['task'] = 'list';
$lang->execution->icons['calendar'] = 'calendar';
$lang->execution->icons['gantt'] = 'lane';
$lang->execution->icons['tree'] = 'treemap';
$lang->execution->icons['grouptask'] = 'sitemap';
$lang->execution->aclList['private'] = "私有(团队成员和项目负责人可访问)";
+107
View File
@@ -0,0 +1,107 @@
<?php
public function setMenu($executionID, $buildID = 0, $extra = '')
{
common::setMenuVars('execution', $executionID);
$execution = $this->getById($executionID);
if(isset($this->lang->execution->menu->kanban))
{
$this->loadModel('project')->setMenu($execution->project);
$this->lang->kanban->menu->execution['subMenu'] = new stdClass();
if($this->app->rawModule == 'tree') unset($this->lang->kanban->menu->execution['subMenu']);
}
$kanbanList = $this->getList($execution->project, 'kanban', 'all');
$currentKanban = zget($kanbanList, $execution->id, '');
if(empty($currentKanban))
{
echo(js::alert($this->lang->execution->accessDenied));
die(js::locate(helper::createLink('project', 'execution', "status=all&projectID={$execution->project}")));
}
$modulePageNav = "";
$modulePageNav .= "<div class='btn-group angle-btn active'><div class='btn-group'>";
$modulePageNav .= "<button data-toggle='dropdown' type='button' class='btn' style='border-radius: 4px;'>{$currentKanban->name} <span class='caret'></span></button>";
$modulePageNav .= "<ul class='dropdown-menu'>";
foreach($kanbanList as $kanbanID => $kanban)
{
$modulePageNav .= '<li>' . html::a(helper::createLink('execution', $this->app->rawMethod, "execution=$kanban->id"), $kanban->name) . '</li>';
}
$modulePageNav .= "</ul></div></div>";
if(in_array($this->app->rawMethod, array('task', 'calendar', 'gantt', 'tree', 'grouptask'))) $this->lang->TRActions = $this->getTRActions($this->app->rawMethod);
if(in_array($this->app->rawMethod, array('relation', 'maintainrelation'))) $this->lang->TRActions = $this->getTRActions('gantt');
$this->lang->modulePageNav = $modulePageNav;
}
public function getTree($executionID)
{
$fullTrees = $this->loadModel('tree')->getTaskStructure($executionID, 0);
array_unshift($fullTrees, array('id' => 0, 'name' => '/', 'type' => 'task', 'actions' => false, 'root' => $executionID));
foreach($fullTrees as $i => $tree)
{
$tree = (object)$tree;
if($tree->type == 'product') array_unshift($tree->children, array('id' => 0, 'name' => '/', 'type' => 'story', 'actions' => false, 'root' => $tree->root));
$fullTree = $this->fillTasksInTree($tree, $executionID);
if(empty($fullTree->children))
{
unset($fullTrees[$i]);
}
else
{
$fullTrees[$i] = $fullTree;
}
}
if(isset($fullTrees[0]) and empty($fullTrees[0]->children)) array_shift($fullTrees);
$newTrees = array();
foreach($fullTrees as $i => $tree)
{
if($tree->type == 'product')
{
foreach($tree->children as $value)
{
$newTrees[] = $value;
}
}
else
{
$newTrees[] = $tree;
}
}
return array_values($newTrees);
}
public function getTRActions($currentMethod)
{
$subMenu = $this->lang->execution->menu;
foreach($subMenu as $key => $value)
{
$tmpValue = explode('|', $value['link']);
$subMenu->$key['name'] = $tmpValue[0];
$subMenu->$key['module'] = $tmpValue[1];
$subMenu->$key['method'] = $tmpValue[2];
$subMenu->$key['vars'] = $tmpValue[3];
}
$TRActions = '';
$TRActions .= "<div class='dropdown'>";
$TRActions .= html::a('javascript:;', "<i class='icon icon-" . $this->lang->execution->icons[$currentMethod]."'></i> " . $subMenu->$currentMethod['name'] . "<span class='caret'></span>", '', "data-toggle='dropdown' class='btn btn-link'");
$TRActions .= "<ul class='dropdown-menu pull-right'>";
foreach($subMenu as $subKey => $subName)
{
$TRActions .= '<li>' . html::a(helper::createLink('execution', $subName['method'], $subName['vars']), "<i class='icon icon-" . $this->lang->execution->icons[$subName['method']] . "'></i> " . $subName['name']) . '</li>';
}
$TRActions .= "</ul></div>";
return $TRActions;
}
@@ -0,0 +1,115 @@
<?php
/**
* The create view of execution module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package execution
* @version $Id: create.html.php 4728 2013-05-03 06:14:34Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
?>
<?php if(isset($tips)):?>
<?php $defaultURL = $this->createLink('execution', 'kanban', 'executionID=' . $executionID);?>
<?php die(js::locate($defaultURL));?>
<?php endif;?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<?php include $app->getModuleRoot() . 'common/view/kindeditor.html.php';?>
<?php include '../lang/' . $this->app->getClientLang() . '/lite.php';?>
<?php js::import($jsRoot . 'misc/date.js');?>
<?php js::set('weekend', $config->execution->weekend);?>
<?php js::set('holders', $lang->execution->placeholder);?>
<?php js::set('errorSameProducts', $lang->execution->errorSameProducts);?>
<?php js::set('errorSameBranches', $lang->execution->errorSameBranches);?>
<?php js::set('productID', empty($productID) ? 0 : $productID);?>
<?php js::set('isStage', $isStage);?>
<?php js::set('copyExecutionID', $copyExecutionID);?>
<?php js::set('systemMode', $config->systemMode);?>
<?php js::set('projectCommon', $lang->project->common);?>
<?php js::set('multiBranchProducts', $multiBranchProducts);?>
<?php js::set('systemMode', $config->systemMode);?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->execution->create;?></h2>
</div>
<form class='form-indicator main-form form-ajax' method='post' target='hiddenwin' id='dataform'>
<table class='table table-form'>
<?php if($config->systemMode == 'new'):?>
<tr>
<th class='w-120px'><?php echo $lang->execution->projectName;?></th>
<td class="col-main"><?php echo html::select("project", $allProjects, $projectID, "class='form-control chosen' required onchange='refreshPage(this.value)'");?></td>
<td colspan='2'></td>
</tr>
<?php endif;?>
<tr>
<th class='w-120px'><?php echo $lang->execution->name;?></th>
<td class="col-main">
<?php echo html::input('name', $name, "class='form-control' required");?>
<?php echo html::hidden('begin', date('Y-m-d'));?>
<?php echo html::hidden('end', date('Y-m-d'));?>
<?php echo html::hidden('days', '1');?>
</td>
<td colspan='2'></td>
</tr>
<tr>
<th><?php echo $lang->execution->code;?></th>
<td><?php echo html::input('code', $code, "class='form-control' required");?></td><td></td><td></td>
</tr>
<tr class='hide'>
<th><?php echo $lang->execution->status;?></th>
<td><?php echo html::hidden('status', 'wait');?></td>
<td></td>
<td></td>
</tr>
<?php $this->printExtendFields('', 'table', 'columns=3');?>
<tr>
<th><?php echo $lang->execution->owner;?></th>
<td><?php echo html::select('PM', $pmUsers, empty($copyExecution) ? '' : $copyExecution->PM, "class='form-control chosen'");?></td>
</tr>
<tr>
<th><?php echo $lang->execution->team;?></th>
<td colspan='3'><?php echo html::select('teamMembers[]', $users, '', "class='form-control chosen' multiple"); ?></td>
</tr>
<tr>
<th><?php echo $lang->execution->desc;?></th>
<td colspan='3'>
<?php echo $this->fetch('user', 'ajaxPrintTemplates', 'type=execution&link=desc');?>
<?php echo html::textarea('desc', '', "rows='6' class='form-control kindeditor' hidefocus='true'");?>
</td>
</tr>
<tr>
<th><?php echo $lang->execution->acl;?></th>
<td colspan='3'><?php echo nl2br(html::radio('acl', $lang->execution->aclList, $acl, "onclick='setWhite(this.value);'", 'block'));?></td>
</tr>
<tr class="hidden" id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td colspan='2'>
<div class='input-group'>
<?php echo html::select('whitelist[]', $users, $whitelist, 'class="form-control chosen" multiple');?>
<?php echo $this->fetch('my', 'buildContactLists', "dropdownName=whitelist");?>
</div>
</td>
</tr>
<tr>
<td colspan='4' class='text-center form-actions'>
<?php echo html::submitButton();?>
<?php echo html::backButton();?>
<?php
unset($allProducts[0]);
echo html::hidden("products[]", key($allProducts));
?>
<?php echo html::hidden("PO", '');?>
<?php echo html::hidden("QD", '');?>
<?php echo html::hidden("RD", '');?>
<?php echo html::hidden("type", 'kanban');?>
<?php echo html::hidden("vision", 'lite');?>
</td>
</tr>
</table>
</form>
</div>
</div>
<?php include $app->getModuleRoot() . 'common/view/footer.html.php';?>
@@ -0,0 +1,10 @@
<script>
$('#begin').closest('tr').hide();
$('#days').closest('tr').hide();
$('#productsBox').closest('tr').hide();
$('#plansBox').closest('tr').hide();
$('#PO').closest('.input-group').hide();
$('#QD').closest('.input-group').hide();
$('#RD').closest('.input-group').hide();
$('#PM').closest('.input-group').find('.input-group-addon').hide();
</script>
@@ -0,0 +1,10 @@
<style>
.kanban-card .title i.icon-checked {display: none;}
.kanban-card .infos .info-id {display: none;}
.course-groupBy {width: 105px;}
.course-groupBy li > a {float: left;}
.course-groupBy .icon-check {left: 5px !important;}
</style>
<script>
$('#mainMenu').remove();
</script>
@@ -0,0 +1,3 @@
<script>
$('#importActionMenu li:last-child').remove();
</script>
@@ -0,0 +1 @@
<?php include $this->app->getExtensionRoot() . 'biz/flow/ext/view/' . basename(__FILE__);?>
@@ -0,0 +1 @@
<?php include $this->app->getExtensionRoot() . 'biz/flow/ext/view/' . basename(__FILE__);?>
@@ -0,0 +1,2 @@
<?php
include dirname(dirname(__FILE__)) . '/resource.php';
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,2 @@
<?php
include dirname(dirname(__FILE__)) . '/resource.php';
@@ -0,0 +1,6 @@
<script>
$(function()
{
$('#submit').parent().append('<input type="hidden" name="vision" id="vision" value="lite">');
});
</script>
@@ -0,0 +1,45 @@
<?php
/**
* The create view of group module for lite vision of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package group
* @version $Id: create.html.php 4129 2013-01-18 01:58:14Z wwccss $
* @link http://www.zentao.net
*/
?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2><?php echo $lang->group->create;?></h2>
</div>
<form method='post' target='hiddenwin' id='dataform'>
<table align='center' class='table table-form'>
<tr>
<th><?php echo $lang->group->name;?></th>
<td class='required'><?php echo html::input('name', '', "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->group->desc;?></th>
<td><?php echo html::textarea('desc', '', "rows=5 class=form-control");?></td>
</tr>
<?php if($this->app->tab != 'project'):?>
<tr>
<th><?php echo $lang->group->limited;?></th>
<td><?php echo html::checkbox('limited', '');?></td>
</tr>
<?php endif;?>
<tr>
<td colspan='2' class='text-center'>
<?php
echo html::hidden('vision', 'lite');
echo html::submitButton();
?>
</td>
</tr>
</table>
</form>
</div>
<?php include $app->getModuleRoot() . 'common/view/footer.html.php';?>
@@ -0,0 +1,3 @@
<script>
$('select[name="version"]').parent().remove();
</script>
@@ -0,0 +1,8 @@
<?php
$lang->kanban->taskColumn = array();
$lang->kanban->taskColumn['wait'] = '未开始';
$lang->kanban->taskColumn['developing'] = '进行中';
$lang->kanban->taskColumn['developed'] = '已完成';
$lang->kanban->taskColumn['pause'] = '已暂停';
$lang->kanban->taskColumn['canceled'] = '已取消';
$lang->kanban->taskColumn['closed'] = '已关闭';
+174
View File
@@ -0,0 +1,174 @@
<?php
public function __construct($appName = '')
{
parent::__construct($appName);
$this->lang->kanban->menu = new stdclass();
}
public function getKanban4Group($executionID, $browseType, $groupBy)
{
/* Get card data. */
$cardList = array();
if($browseType == 'story') $cardList = $this->loadModel('story')->getExecutionStories($executionID, 0, 0, 't1.`order`_desc', 'allStory');
if($browseType == 'bug') $cardList = $this->loadModel('bug')->getExecutionBugs($executionID);
if($browseType == 'task') $cardList = $this->loadModel('execution')->getKanbanTasks($executionID, "id");
$lanes = $this->getLanes4Group($executionID, $browseType, $groupBy, $cardList);
if(empty($lanes)) return array();
$columns = $this->dao->select('t1.*, t2.`type` as columnType')->from(TABLE_KANBANCELL)->alias('t1')
->leftJoin(TABLE_KANBANCOLUMN)->alias('t2')->on('t1.`column` = t2.id')
->where('t1.kanban')->eq($executionID)
->andWhere('t1.`type`')->eq($browseType)
->fetchAll();
$cardGroup = array();
foreach($columns as $column)
{
if(empty($column->cards)) continue;
foreach($cardList as $card)
{
if(strpos($column->cards, ",$card->id,") !== false) $cardGroup[$column->columnType][$card->id] = $card;
}
}
/* Build kanban group data. */
$kanbanGroup = array();
foreach($lanes as $laneID => $lane)
{
$laneData = array();
$columnData = array();
$columnList = $this->lang->kanban->{$browseType . 'Column'};
$laneData['id'] = $groupBy . $laneID;
$laneData['laneID'] = $groupBy . $laneID;
$laneData['name'] = (($groupBy == 'pri' or $groupBy == 'severity') and $laneID) ? $this->lang->$browseType->$groupBy . ':' . $lane->name : $lane->name;
$laneData['color'] = $lane->color;
$laneData['order'] = $lane->order;
$laneData['defaultCardType'] = $browseType;
/* Construct kanban column data. */
foreach($columnList as $columnID => $columnName)
{
$parentColumn = '';
if(in_array($columnID, array('testing', 'tested'))) $parentColumn = 'test';
if(in_array($columnID, array('fixing', 'fixed'))) $parentColumn = 'resolving';
$columnData[$columnID]['id'] = $columnID;
$columnData[$columnID]['type'] = $columnID;
$columnData[$columnID]['name'] = $columnName;
$columnData[$columnID]['color'] = '#333';
$columnData[$columnID]['limit'] = -1;
$columnData[$columnID]['laneType'] = $browseType;
$columnData[$columnID]['asParent'] = in_array($columnID, array('develop', 'test', 'resolving')) ? true : false;
$columnData[$columnID]['parentType'] = $parentColumn;
$cardOrder = 1;
$objects = zget($cardGroup, $columnID, array());
foreach($objects as $object)
{
if(empty($object)) continue;
$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;
$cardData['id'] = $object->id;
$cardData['order'] = $cardOrder;
$cardData['pri'] = $object->pri ? $object->pri : '';
$cardData['estimate'] = $browseType == 'bug' ? '' : $object->estimate;
$cardData['assignedTo'] = $object->assignedTo;
$cardData['deadline'] = $browseType == 'story' ? '' : $object->deadline;
$cardData['severity'] = $browseType == 'bug' ? $object->severity : '';
if($browseType == 'task')
{
$cardData['name'] = $object->name;
}
else
{
$cardData['title'] = $object->title;
}
$laneData['cards'][$columnID][] = $cardData;
$cardOrder ++;
}
if(!isset($laneData['cards'][$columnID])) $laneData['cards'][$columnID] = array();
}
$kanbanGroup[$groupBy]['id'] = $groupBy . $laneID;
$kanbanGroup[$groupBy]['columns'] = array_values($columnData);
$kanbanGroup[$groupBy]['lanes'][] = $laneData;
$kanbanGroup[$groupBy]['defaultCardType'] = $browseType;
}
return $kanbanGroup;
}
/**
* Get card group by execution id.
*
* @param int $kanbanID
* @param string $browseType all|task|bug|story
* @param string $orderBy
* @access public
* @return array
*/
public function getCardGroupByExecution($executionID, $browseType = 'all', $orderBy = 'id_asc')
{
$cards = $this->dao->select('t1.*, t2.type as columnType')
->from(TABLE_KANBANCELL)->alias('t1')
->leftJoin(TABLE_KANBANCOLUMN)->alias('t2')->on('t1.column=t2.id')
->where('t1.kanban')->eq($executionID)
->beginIF($browseType != 'all')->andWhere('t1.type')->eq($browseType)->fi()
->orderby($orderBy)
->fetchgroup('lane', 'column');
/* Get group objects. */
if($browseType == 'all' or $browseType == 'story') $objectGroup['story'] = $this->loadModel('story')->getExecutionStories($executionID, 0, 0, 't1.`order`_desc', 'allStory');
if($browseType == 'all' or $browseType == 'bug') $objectGroup['bug'] = $this->loadModel('bug')->getExecutionBugs($executionID);
if($browseType == 'all' or $browseType == 'task') $objectGroup['task'] = $this->loadModel('execution')->getKanbanTasks($executionID, "id");
$taskCardMenu = $this->getKanbanCardMenu($executionID, $objectGroup['task'], 'task');
$cardGroup = array();
foreach($cards as $laneID => $cells)
{
foreach($cells as $columnID => $cell)
{
$cardIdList = array_filter(explode(',', $cell->cards));
$cardOrder = 1;
foreach($cardIdList as $cardID)
{
$cardData = array();
$objects = zget($objectGroup, $cell->type, array());
$object = zget($objects, $cardID, array());
if(empty($object)) continue;
$cardData['id'] = $object->id;
$cardData['order'] = $cardOrder++;
$cardData['pri'] = $object->pri ? $object->pri : '';
$cardData['estimate'] = $cell->type == 'bug' ? '' : $object->estimate;
$cardData['assignedTo'] = $object->assignedTo;
$cardData['deadline'] = $cell->type == 'story' ? '' : $object->deadline;
$cardData['severity'] = $cell->type == 'bug' ? $object->severity : '';
$cardData['acl'] = 'open';
$cardData['lane'] = $laneID;
$cardData['column'] = $cell->column;
$cardData['menus'] = $taskCardMenu[$cardID];
if($cell->type == 'task')
{
$cardData['name'] = $object->name;
}
else
{
$cardData['title'] = $object->title;
}
$cardGroup[$laneID][$cell->columnType][] = $cardData;
}
}
}
return $cardGroup;
}
@@ -0,0 +1,7 @@
<script>
$(function()
{
$('#laneTypetask').closest('tr').hide();
$('#laneTypeBox #laneTypetask').prop('checked', true).change();
})
</script>
@@ -0,0 +1,32 @@
<?php
$config->message->objectTypes = array();
$config->message->objectTypes['story'] = array('opened', 'edited', 'commented', 'changed', 'reviewed', 'closed', 'activated', 'assigned');
$config->message->objectTypes['project'] = array('opened', 'edited', 'started', 'delayed', 'suspended', 'closed', 'activated', 'undeleted');
$config->message->objectTypes['task'] = array('opened', 'edited', 'assigned', 'archived', 'finished', 'deleted');
$config->message->objectTypes['todo'] = array('opened', 'edited');
$config->message->objectTypes['doc'] = array('created', 'edited');
$config->message->available = array();
$config->message->available['mail']['story'] = $config->message->objectTypes['story'];
$config->message->available['mail']['task'] = $config->message->objectTypes['task'];
$config->message->available['mail']['doc'] = $config->message->objectTypes['doc'];
$config->message->available['webhook'] = $config->message->objectTypes;
$config->message->available['message']['story'] = $config->message->objectTypes['story'];
$config->message->available['message']['task'] = $config->message->objectTypes['task'];
$config->message->available['message']['todo'] = $config->message->objectTypes['todo'];
$config->message->available['message']['doc'] = $config->message->objectTypes['doc'];
$config->message->typeLink = array();
$config->message->typeLink['mail'] = 'mail|index';
$config->message->typeLink['webhook'] = 'webhook|browse';
$config->message->setting = array();
$config->message->setting['message']['setting'] = $config->message->available['message'];
$config->message->setting['webhook']['setting'] = $config->message->available['webhook'];
$config->message->setting['mail']['setting'] = $config->message->available['mail'];
$config->message->browser = new stdclass();
$config->message->browser->turnon = 1;
$config->message->browser->pollTime = 300;
@@ -0,0 +1,3 @@
<?php
$lang->message->label->archived = '归档';
$lang->message->label->deleted = '删除';
@@ -0,0 +1,2 @@
<?php
unset($lang->misc->zentao->service);
@@ -0,0 +1,3 @@
<script>
$('#zentaoLinks > .row > .col-sm-2').removeClass('col-sm-2').addClass('col-sm-4');
</script>
@@ -0,0 +1,3 @@
<?php
$calendarHookFile = $app->getExtensionRoot() . 'biz/my/ext/view/effort.calendar.html.hook.php';
if(file_exists($calendarHookFile)) include $calendarHookFile;
+319
View File
@@ -0,0 +1,319 @@
<?php
/**
* The task view file of dashboard module for lite vision of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Wenrui LI <liwenrui@easycorp.ltd>
* @package dashboard
* @version $Id: task.html.php 5101 2013-07-12 00:44:27Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
?>
<?php include $this->app->getModuleRoot() . '/common/view/header.html.php';?>
<?php js::set('mode', $mode);?>
<?php js::set('total', $pager->recTotal);?>
<?php js::set('rawMethod', $app->rawMethod);?>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
<?php $recTotalLabel = " <span class='label label-light label-badge'>{$pager->recTotal}</span>"; ?>
<?php if($app->rawMethod == 'contribute'):?>
<?php
echo html::a(inlink($app->rawMethod, "mode=$mode&type=assignedTo"), "<span class='text'>{$lang->my->taskMenu->assignedToMe}</span>" . ($type == 'assignedTo' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'assignedTo' ? ' btn-active-text' : '') . "'");
echo html::a(inlink($app->rawMethod, "mode=$mode&type=openedBy"), "<span class='text'>{$lang->my->taskMenu->openedByMe}</span>" . ($type == 'openedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'openedBy' ? ' btn-active-text' : '') . "'");
echo html::a(inlink($app->rawMethod, "mode=$mode&type=finishedBy"), "<span class='text'>{$lang->my->taskMenu->finishedByMe}</span>" . ($type == 'finishedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'finishedBy' ? ' btn-active-text' : '') . "'");
echo html::a(inlink($app->rawMethod, "mode=$mode&type=closedBy"), "<span class='text'>{$lang->my->taskMenu->closedByMe}</span>" . ($type == 'closedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'closedBy' ? ' btn-active-text' : '') . "'");
echo html::a(inlink($app->rawMethod, "mode=$mode&type=canceledBy"), "<span class='text'>{$lang->my->taskMenu->canceledByMe}</span>" . ($type == 'canceledBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'canceledBy' ? ' btn-active-text' : '') . "'");
?>
<?php endif;?>
</div>
</div>
<div id="mainContent">
<?php if(empty($tasks)):?>
<div class="table-empty-tip">
<p><span class="text-muted"><?php echo $lang->task->noTask;?></span></p>
</div>
<?php else:?>
<form id='myTaskForm' class="main-table table-task skip-iframe-modal" method="post">
<?php $canBatchEdit = (common::hasPriv('task', 'batchEdit') and $type == 'assignedTo');?>
<?php $canBatchClose = (common::hasPriv('task', 'batchClose') and $type != 'closedBy');?>
<table class="table has-sort-head table-fixed" id='taskTable'>
<?php $vars = "mode=$mode&type=$type&orderBy=%s&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID"; ?>
<thead>
<tr>
<th class="c-id">
<?php if($canBatchEdit or $canBatchClose):?>
<div class="checkbox-primary check-all" title="<?php echo $lang->selectAll?>">
<label></label>
</div>
<?php endif;?>
<?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?>
</th>
<th class='c-pri'><?php common::printOrderLink('pri', $orderBy, $vars, $lang->priAB);?></th>
<th class='c-name'><?php common::printOrderLink('name', $orderBy, $vars, $lang->task->name);?></th>
<?php if($config->systemMode == 'new'):?>
<th class='c-project'><?php common::printOrderLink('project', $orderBy, $vars, $lang->my->projects);?></th>
<?php endif;?>
<th class='c-project'><?php common::printOrderLink('execution', $orderBy, $vars, $lang->my->executions);?></th>
<?php if($type != 'openedBy'): ?>
<th class='c-user'><?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
<?php endif;?>
<th class='c-date text-center'><?php common::printOrderLink('deadline', $orderBy, $vars, $lang->task->deadlineAB);?></th>
<?php if($type != 'assignedTo'): ?>
<th class='c-user'><?php common::printOrderLink('assignedTo', $orderBy, $vars, $lang->task->assignedTo);?></th>
<?php endif;?>
<?php if($type != 'finishedBy'): ?>
<th class='c-user'><?php common::printOrderLink('finishedBy', $orderBy, $vars, $lang->task->finishedBy);?></th>
<?php endif;?>
<th class='c-hours'><?php common::printOrderLink('estimate', $orderBy, $vars, $lang->task->estimateAB);?></th>
<th class='c-hours'><?php common::printOrderLink('consumed', $orderBy, $vars, $lang->task->consumedAB);?></th>
<th class='c-hours'><?php common::printOrderLink('left', $orderBy, $vars, $lang->task->leftAB);?></th>
<th class='c-status'><?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
<th class='c-actions-6'><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody id='myTaskList'>
<?php foreach($tasks as $task):?>
<?php $canBeChanged = common::canBeChanged('task', $task);?>
<tr data-id='<?php echo $task->id;?>' data-status='<?php echo $task->status?>' data-estimate='<?php echo $task->estimate?>' data-consumed='<?php echo $task->consumed?>' data-left='<?php echo $task->left?>'>
<td class="c-id">
<?php if($canBatchEdit or $canBatchClose):?>
<div class="checkbox-primary">
<input type='checkbox' name='taskIDList[]' value='<?php echo $task->id;?>' <?php if(!$canBeChanged) echo 'disabled';?>/>
<label></label>
</div>
<?php endif;?>
<?php printf('%03d', $task->id);?>
</td>
<td class="c-pri"><span class='label-pri <?php echo 'label-pri-' . $task->pri;?>' title='<?php echo zget($lang->task->priList, $task->pri);?>'><?php echo zget($lang->task->priList, $task->pri);?></span></td>
<td class='c-name <?php if(!empty($task->children)) echo 'has-child';?>' title='<?php echo $task->name?>'>
<?php if(!empty($task->team)) echo '<span class="label label-badge label-light">' . $this->lang->task->multipleAB . '</span> ';?>
<?php
if($task->parent > 0)
{
echo '<span class="label label-badge label-light">' . $this->lang->task->childrenAB . '</span> ' . html::a($this->createLink('task', 'view', "taskID=$task->id", '', '', $task->project), $task->parentName . ' / '. $task->name, '', "title='{$task->parentName} / {$task->name}'");
}
else
{
echo html::a($this->createLink('task', 'view', "taskID=$task->id", '', '', $task->project), $task->name, null, "style='color: $task->color'");
}
?>
<?php if(!empty($task->children)) echo '<a class="task-toggle" data-id="' . $task->id . '"><i class="icon icon-angle-double-right"></i></a>';?>
</td>
<?php if($config->systemMode == 'new'):?>
<td class='c-project' title="<?php echo $task->projectName;?>"><?php echo html::a($this->createLink('project', 'index', "projectID=$task->project"), $task->projectName);?></td>
<?php endif;?>
<td class='c-project' title="<?php echo $task->executionName;?>"><?php echo html::a($this->createLink('execution', 'task', "executionID=$task->execution"), $task->executionName, '');?></td>
<?php if($type != 'openedBy'): ?>
<td class='c-user'><?php echo zget($users, $task->openedBy);?></td>
<?php endif;?>
<td class="text-center <?php echo isset($task->delay) ? 'delayed' : '';?>"><?php if(substr($task->deadline, 0, 4) > 0) echo substr($task->deadline, 5, 6);?></td>
<?php if($type != 'assignedTo'): ?>
<td class="c-assignedTo has-btn"> <?php $this->task->printAssignedHtml($task, $users);?></td>
<?php endif;?>
<?php if($type != 'finishedBy'): ?>
<td class='c-user'><?php echo zget($users, $task->finishedBy);?></td>
<?php endif;?>
<td class='c-hours' title="<?php echo round($task->estimate, 1) . ' ' . $lang->execution->workHour;?>"><?php echo round($task->estimate, 1) . $lang->execution->workHourUnit;?></td>
<td class='c-hours' title="<?php echo round($task->consumed, 1) . ' ' . $lang->execution->workHour;?>"><?php echo round($task->consumed, 1) . $lang->execution->workHourUnit;?></td>
<td class='c-hours' title="<?php echo round($task->left, 1) . ' ' . $lang->execution->workHour;?>"><?php echo round($task->left, 1) . $lang->execution->workHourUnit;?></td>
<td class='c-status'>
<?php $storyChanged = (!empty($task->storyStatus) and $task->storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion and !in_array($task->status, array('cancel', 'closed')));?>
<?php !empty($storyChanged) ? print("<span class='status-story status-changed'>{$this->lang->my->storyChanged}</span>") : print("<span class='status-task status-{$task->status}'> " . $this->processStatus('task', $task) . "</span>");?>
</td>
<td class='c-actions'>
<?php
if($canBeChanged)
{
if($task->needConfirm)
{
$this->lang->task->confirmStoryChange = $this->lang->confirm;
common::printIcon('task', 'confirmStoryChange', "taskid=$task->id", '', 'list', '', 'hiddenwin', '', '', '', '', $task->project);
}
else
{
if($task->status != 'pause') common::printIcon('task', 'start', "taskID=$task->id", $task, 'list', '', '', 'iframe', true, '', '', $task->project);
if($task->status == 'pause') common::printIcon('task', 'restart', "taskID=$task->id", $task, 'list', '', '', 'iframe', true, '', '', $task->project);
common::printIcon('task', 'close', "taskID=$task->id", $task, 'list', '', '', 'iframe', true, '', '', $task->project);
common::printIcon('task', 'finish', "taskID=$task->id", $task, 'list', '', '', 'iframe', true, '', '', $task->project);
common::printIcon('task', 'recordEstimate', "taskID=$task->id", $task, 'list', 'time', '', 'iframe', true, '', '', $task->project);
common::printIcon('task', 'edit', "taskID=$task->id", $task, 'list', '', '', 'iframe', true, "data-width='95%'", '', $task->project);
common::printIcon('task', 'batchCreate', "executionID=$task->execution&storyID=$task->story&moduleID=$task->module&taskID=$task->id&ifame=true", $task, 'list', 'split', '', 'iframe', true, "data-width='95%'", $this->lang->task->children, $task->project);
}
}
?>
</td>
</tr>
<?php if(!empty($task->children)):?>
<?php $i = 0;?>
<?php foreach($task->children as $key => $child):?>
<?php $class = $i == 0 ? ' table-child-top' : '';?>
<?php $class .= ($i + 1 == count($task->children)) ? ' table-child-bottom' : '';?>
<tr class='table-children<?php echo $class;?> parent-<?php echo $task->id;?>' data-id='<?php echo $child->id?>' data-status='<?php echo $child->status?>' data-estimate='<?php echo $child->estimate?>' data-consumed='<?php echo $child->consumed?>' data-left='<?php echo $child->left?>'>
<td class="c-id">
<?php if($canBatchEdit or $canBatchClose):?>
<div class="checkbox-primary">
<input type='checkbox' name='taskIDList[]' value='<?php echo $child->id;?>' <?php if(!$canBeChanged) echo 'disabled';?>/>
<label></label>
</div>
<?php endif;?>
<?php printf('%03d', $child->id);?>
</td>
<td class="c-pri"><span class='label-pri <?php echo 'label-pri-' . $child->pri;?>' title='<?php echo zget($lang->task->priList, $child->pri);?>'><?php echo zget($lang->task->priList, $child->pri);?></span></td>
<td class='c-name' title='<?php echo $child->name?>'>
<?php if($child->parent > 0) echo '<span class="label label-badge label-light">' . $this->lang->task->childrenAB . '</span> ';?>
<?php echo html::a($this->createLink('task', 'view', "taskID=$child->id", '', '', $child->project), $child->name, null, "style='color: $child->color'");?>
</td>
<?php if($config->systemMode == 'new'):?>
<td class='c-project' title="<?php echo $child->projectName;?>"><?php echo html::a($this->createLink('project', 'view', "projectID=$child->project"), $child->projectName);?></td>
<?php endif;?>
<td class='c-project' title="<?php echo $child->projectName;?>"><?php echo html::a($this->createLink('execution', 'task', "executionID=$child->project"), $child->executionName, '');?></td>
<?php if($type != 'openedBy'): ?>
<td class='c-user'><?php echo zget($users, $child->openedBy);?></td>
<?php endif;?>
<td class="text-center <?php echo isset($child->delay) ? 'delayed' : '';?>"><?php if(substr($child->deadline, 0, 4) > 0) echo substr($child->deadline, 5, 6);?></td>
<?php if($type != 'assignedTo'): ?>
<td class="c-assignedTo has-btn"> <?php $this->task->printAssignedHtml($child, $users);?></td>
<?php endif;?>
<?php if($type != 'finishedBy'): ?>
<td class='c-user'><?php echo zget($users, $child->finishedBy);?></td>
<?php endif;?>
<td class='c-hours' title="<?php echo round($child->estimate, 1) . ' ' . $lang->execution->workHour;?>"><?php echo round($child->estimate, 1) . ' ' . $lang->execution->workHourUnit;?></td>
<td class='c-hours' title="<?php echo round($child->consumed, 1) . ' ' . $lang->execution->workHour;?>"><?php echo round($child->consumed, 1) . ' ' . $lang->execution->workHourUnit;?></td>
<td class='c-hours' title="<?php echo round($child->left, 1) . ' ' . $lang->execution->workHour;?>"><?php echo round($child->left, 1) . ' ' . $lang->execution->workHourUnit;?></td>
<td class='c-status'>
<?php $storyChanged = (!empty($child->storyStatus) and $child->storyStatus == 'active' and $child->latestStoryVersion > $child->storyVersion and !in_array($child->status, array('cancel', 'closed')));?>
<?php !empty($storyChanged) ? print("<span class='status-story status-changed'>{$this->lang->my->storyChanged}</span>") : print("<span class='status-task status-{$child->status}'> " . $this->processStatus('task', $child) . "</span>");?>
</td>
<td class='c-actions'>
<?php
if($canBeChanged)
{
if($child->needConfirm)
{
$this->lang->task->confirmStoryChange = $this->lang->confirm;
common::printIcon('task', 'confirmStoryChange', "taskid=$child->id", '', 'list', '', 'hiddenwin', '', '', '', '', $child->project);
}
else
{
if($child->status != 'pause') common::printIcon('task', 'start', "taskID=$child->id", $child, 'list', '', '', 'iframe', true, '', '', $child->project);
if($child->status == 'pause') common::printIcon('task', 'restart', "taskID=$child->id", $child, 'list', '', '', 'iframe', true, '', '', $child->project);
common::printIcon('task', 'close', "taskID=$child->id", $child, 'list', '', '', 'iframe', true, '', '', $child->project);
common::printIcon('task', 'finish', "taskID=$child->id", $child, 'list', '', '', 'iframe', true, '', '', $child->project);
common::printIcon('task', 'recordEstimate', "taskID=$child->id", $child, 'list', 'time', '', 'iframe', true, '', '', $child->project);
common::printIcon('task', 'edit', "taskID=$child->id", $child, 'list', '', '', '', '', '', '', $child->project);
common::printIcon('task', 'batchCreate', "executionID=$child->execution&storyID=$child->story&moduleID=$child->module&taskID=$child->id&iframe=true", $child, 'list', 'split', '', 'iframe', true, '', $this->lang->task->children, $child->project);
}
}
?>
</td>
</tr>
<?php $i ++;?>
<?php endforeach;?>
<?php endif;?>
<?php endforeach;?>
</tbody>
</table>
<div class="table-footer">
<?php if($canBatchClose or $canBatchEdit):?>
<div class="checkbox-primary check-all"><label><?php echo $lang->selectAll?></label></div>
<?php endif;?>
<div class="table-actions btn-toolbar">
<?php
if($canBatchEdit)
{
$actionLink = $this->createLink('task', 'batchEdit');
$misc = "data-form-action='$actionLink'";
echo html::commonButton($lang->edit, $misc);
}
if($canBatchClose)
{
$actionLink = $this->createLink('task', 'batchClose', null, '', '', $task->project);
echo html::commonButton($lang->close, "onclick=\"setFormAction('$actionLink', 'hiddenwin')\"");
}
?>
</div>
<div class="table-statistic"><?php echo $summary;?></div>
<?php $pager->show('right', 'pagerjs');?>
</div>
</form>
<?php endif;?>
</div>
<?php js::set('tasks', $tasks);?>
<script>
$(function()
{
/* Update table summary text. */
var checkedSummary = '<?php echo $lang->execution->checkedSummary?>';
var pageSummary = '<?php echo $lang->execution->pageSummary?>';
$('#myTaskForm').table(
{
hot: true,
replaceId: 'myTaskList',
statisticCreator: function(table)
{
var $table = table.getTable();
var $checkedRows = $table.find(table.isDataTable ? '.datatable-row-left.checked' : 'tbody>tr.checked');
var $originTable = table.isDataTable ? table.$.find('.datatable-origin') : null;
var checkedTotal = $checkedRows.length;
var $rows = checkedTotal ? $checkedRows : $table.find(table.isDataTable ? '.datatable-rows .datatable-row-left' : 'tbody>tr');
var checkedWait = 0;
var checkedDoing = 0;
var checkedEstimate = 0;
var checkedConsumed = 0;
var checkedLeft = 0;
var taskIdList = [];
$rows.each(function()
{
var $row = $(this);
if ($originTable)
{
$row = $originTable.find('tbody>tr[data-id="' + $row.data('id') + '"]');
}
var data = $row.data();
taskIdList.push(data.id);
var status = data.status;
if(status === 'wait') checkedWait++;
if(status === 'doing') checkedDoing++;
var canStatistics = false;
if(!$row.hasClass('table-children'))
{
canStatistics = true;
}
else
{
var parentID = 0;
var classes = $row.attr('class').split(' ');
for(i in classes)
{
if(classes[i].indexOf('parent-') >= 0) parentID = classes[i].replace('parent-', '');
}
if(parentID && taskIdList.indexOf(parseInt(parentID)) < 0) canStatistics = true;
}
if(canStatistics)
{
checkedEstimate += Number(data.estimate);
checkedConsumed += Number(data.consumed);
if(status != 'cancel' && status != 'closed') checkedLeft += Number(data.left);
}
});
return (checkedTotal ? checkedSummary : pageSummary).replace('%total%', $rows.length).replace('%wait%', checkedWait)
.replace('%doing%', checkedDoing)
.replace('%estimate%', checkedEstimate.toFixed(1))
.replace('%consumed%', checkedConsumed.toFixed(1))
.replace('%left%', checkedLeft.toFixed(1));
}
})
});
</script>
<?php include $this->app->getModuleRoot() . '/common/view/footer.html.php';?>
@@ -0,0 +1,3 @@
<?php
$calendarHookFile = $app->getExtensionRoot() . 'biz/my/ext/view/todo.calendar.html.hook.php';
if(file_exists($calendarHookFile)) include $calendarHookFile;
@@ -0,0 +1,8 @@
<style>
#object_chosen{display:none;}
</style>
<script>
var $object = $('#object');
$object.prev().hide();
$object.hide();
</script>
@@ -0,0 +1,7 @@
<?php
unset($config->product->search['fields']['stage']);
unset($config->product->search['fields']['product']);
unset($config->product->search['fields']['plan']);
unset($config->product->search['fields']['source']);
unset($config->product->search['fields']['sourceNote']);
unset($config->product->search['fields']['fromBug']);
@@ -0,0 +1,188 @@
<?php
class product extends control
{
public function browse($productID = 0, $branch = '', $browseType = '', $param = 0, $storyType = 'story', $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1, $projectID = 0)
{
/* Load datatable and execution. */
$this->loadModel('datatable');
$this->loadModel('execution');
$this->loadModel('user');
$projectProducts = $this->loadModel('product')->getProducts($projectID);
$productPlans = $this->execution->getPlans($projectProducts);
$this->products = array();
foreach($projectProducts as $productID => $product) $this->products[$productID] = $product->name;
reset($projectProducts);
$productID = key($projectProducts);
$product = $projectProducts[$productID];
$showBranch = $this->loadModel('branch')->showBranch($productID, 0, $projectID);
if(!empty($product)) $this->session->set('currentProductType', $product->type);
/* Set menu. */
$this->session->set('storyList', $this->app->getURI(true), 'project');
$this->loadModel('project')->setMenu($projectID);
$branches = $this->loadModel('branch')->getList($productID, $projectID, 'all');
$branch = ($this->cookie->preBranch !== '' and $branch === '' and isset($branches[$this->cookie->preBranch])) ? $this->cookie->preBranch : $branch;
$branchID = $branch;
/* Lower browse type. */
$browseType = strtolower($browseType);
/* Set product, module and query. */
setcookie('preProductID', $productID, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
setcookie('preBranch', $branch, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
if($this->cookie->preProductID != $productID or $this->cookie->preBranch != $branch)
{
$_COOKIE['storyModule'] = 0;
setcookie('storyModule', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
}
if($browseType == 'bymodule' or $browseType == '')
{
setcookie('storyModule', (int)$param, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
if($this->app->tab == 'project') setcookie('storyModuleParam', (int)$param, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
$_COOKIE['storyBranch'] = 'all';
setcookie('storyBranch', 'all', 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
if($browseType == '') setcookie('treeBranch', $branch, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
}
$cookieModule = $this->app->tab == 'project' ? $this->cookie->storyModuleParam : $this->cookie->storyModule;
$moduleID = ($browseType == 'bymodule') ? (int)$param : (($browseType == 'bysearch') ? 0 : ($cookieModule ? $cookieModule : 0));
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
/* Set moduleTree. */
$createModuleLink = $storyType == 'story' ? 'createStoryLink' : 'createRequirementLink';
if($browseType == '')
{
setcookie('treeBranch', $branch, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
$browseType = 'unclosed';
}
else
{
$branch = $this->cookie->treeBranch;
}
/* If in project story and not chose product, get project story mdoules. */
$moduleTree = $this->loadModel('tree')->getTreeMenu($productID, 'story', $startModuleID = 0, array('treeModel', $createModuleLink), array('projectID' => $projectID, 'productID' => $productID), 'all', "&param=$param&storyType=$storyType");
if($browseType != 'bymodule') $this->session->set('storyBrowseType', $browseType);
/* Process the order by field. */
if(!$orderBy) $orderBy = $this->cookie->productStoryOrder ? $this->cookie->productStoryOrder : 'id_desc';
setcookie('productStoryOrder', $orderBy, 0, $this->config->webRoot, '', $this->config->cookieSecure, true);
/* Append id for secend sort. */
$sort = common::appendOrder($orderBy);
/* Load pager. */
$this->app->loadClass('pager', $static = true);
if($this->app->getViewType() == 'xhtml') $recPerPage = 10;
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Display of branch label. */
$showBranch = $this->loadModel('branch')->showBranch($productID);
$product = $this->product->getById($productID);
/* Get stories. */
$stories = $this->product->getStories($productID, $branchID, $browseType, $queryID, $moduleID, $storyType, $sort, $pager);
/* Display status of branch. */
$branchOption = array();
$branchTagOption = array();
foreach($branches as $branchInfo)
{
$branchOption[$branchInfo->id] = $branchInfo->name;
$branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : '');
}
/* Process the sql, get the conditon partion, save it to session. */
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story', ($browseType != 'bysearch' and $browseType != 'reviewbyme' and $this->app->rawModule != 'projectstory'));
if(!empty($stories)) $stories = $this->loadModel('story')->mergeReviewer($stories);
/* Get related tasks, bugs, cases count of each story. */
$storyIdList = array();
foreach($stories as $story)
{
$storyIdList[$story->id] = $story->id;
if(!empty($story->children))
{
foreach($story->children as $child) $storyIdList[$child->id] = $child->id;
}
}
$storyTasks = $this->loadModel('task')->getStoryTaskCounts($storyIdList);
$storyBugs = $this->loadModel('bug')->getStoryBugCounts($storyIdList);
$storyCases = $this->loadModel('testcase')->getStoryCaseCounts($storyIdList);
/* Change for requirement story title. */
if($storyType == 'requirement')
{
$this->lang->story->title = str_replace($this->lang->SRCommon, $this->lang->URCommon, $this->lang->story->title);
$this->lang->story->create = str_replace($this->lang->SRCommon, $this->lang->URCommon, $this->lang->story->create);
$this->config->product->search['fields']['title'] = $this->lang->story->title;
unset($this->config->product->search['fields']['plan']);
unset($this->config->product->search['fields']['stage']);
}
/* Build search form. */
$rawModule = $this->app->rawModule;
$rawMethod = $this->app->rawMethod;
$params = $rawModule == 'projectstory' ? "projectID=$projectID&" : '';
$actionURL = $this->createLink($rawModule, $rawMethod, $params . "productID=$productID&branch=$branch&browseType=bySearch&queryID=myQueryID&storyType=$storyType");
$this->config->product->search['onMenuBar'] = 'yes';
$this->product->buildSearchForm($productID, $this->products, $queryID, $actionURL, $branch);
$showModule = !empty($this->config->datatable->productBrowse->showModule) ? $this->config->datatable->productBrowse->showModule : '';
$productName = ($this->app->rawModule == 'projectstory' and empty($productID)) ? $this->lang->product->all : $this->products[$productID];
/* Assign. */
$this->view->title = $productName . $this->lang->colon . $this->lang->product->browse;
$this->view->position[] = $productName;
$this->view->position[] = $this->lang->product->browse;
$this->view->productID = $productID;
$this->view->product = $product;
$this->view->productName = $productName;
$this->view->moduleID = $moduleID;
$this->view->stories = $stories;
$this->view->plans = $this->loadModel('productplan')->getPairs($productID, $branch === 'all' ? '' : $branch, '', true);
$this->view->productPlans = isset($productPlans) ? array(0 => '') + $productPlans : array();
$this->view->summary = $this->product->summary($stories, $storyType);
$this->view->moduleTree = $moduleTree;
$this->view->parentModules = $this->tree->getParents($moduleID);
$this->view->pager = $pager;
$this->view->users = $this->user->getPairs('noletter|pofirst|nodeleted');
$this->view->teamMembers = $this->user->getTeamMemberPairs($projectID);
$this->view->orderBy = $orderBy;
$this->view->browseType = $browseType;
$this->view->modules = $this->tree->getOptionMenu($productID, 'story', 0, $branchID);
$this->view->moduleID = $moduleID;
$this->view->moduleName = ($moduleID and $moduleID !== 'all') ? $this->tree->getById($moduleID)->name : $this->lang->tree->allMenu;
$this->view->branch = $branch;
$this->view->branchID = $branchID;
$this->view->branchOption = $branchOption;
$this->view->branchTagOption = $branchTagOption;
$this->view->showBranch = $showBranch;
$this->view->storyStages = $this->product->batchGetStoryStage($stories);
$this->view->setModule = true;
$this->view->storyTasks = $storyTasks;
$this->view->storyBugs = $storyBugs;
$this->view->storyCases = $storyCases;
$this->view->param = $param;
$this->view->projectID = $projectID;
$this->view->products = $this->products;
$this->view->projectProducts = isset($projectProducts) ? $projectProducts : array();
$this->view->storyType = $storyType;
$this->view->from = $this->app->tab;
$this->view->modulePairs = $showModule ? $this->tree->getModulePairs($productID, 'story', $showModule) : array();
$this->display();
}
}
@@ -0,0 +1,3 @@
<?php
$lang->product->noModule = '您现在还没有目录信息';
$lang->product->storySummary = "本页共 <strong>%s</strong> 个%s,预计 <strong>%s</strong> 个{$lang->hourCommon}";
@@ -0,0 +1,37 @@
<?php
/**
* Get product pairs for lite.
*
* @param string $mode
* @param string $programID
* @return array
*/
public function getPairs($mode = '', $programID = 0)
{
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getProductPairs();
$projects = $this->loadModel('project')->getPairsByProgram();
$projectIdList = array_keys($projects);
$projectProducts = $this->dao->select('t1.branch, t1.plan, t2.*')
->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')
->on('t1.product = t2.id')
->where('t2.deleted')->eq(0)
->andWhere('t1.project')->in($projectIdList)
->beginIF(!$this->app->user->admin and $this->config->vision == 'rnd')->andWhere('t2.id')->in($this->app->user->view->products)->fi()
->andWhere('t2.vision')->eq($this->config->vision)
->fetchPairs('id', 'id');
$products = $this->dao->select('*, IF(INSTR(" closed", status) < 2, 0, 1) AS isClosed')
->from(TABLE_PRODUCT)
->where(1)
->beginIF(strpos($mode, 'all') === false)->andWhere('deleted')->eq(0)->fi()
->beginIF($programID)->andWhere('program')->eq($programID)->fi()
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('status')->ne('closed')->fi()
->beginIF(!$this->app->user->admin and $this->config->vision == 'rnd')->andWhere('id')->in($this->app->user->view->products)->fi()
->andWhere('vision')->eq($this->config->vision)
->andWhere('id')->in($projectProducts)
->fetchPairs('id', 'name');
return $products;
}
@@ -0,0 +1,623 @@
<?php
/**
* The browse view file of product module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package product
* @version $Id: browse.html.php 4909 2013-06-26 07:23:50Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
?>
<?php include $this->app->getModuleRoot() . '/common/view/header.html.php';?>
<?php include $this->app->getModuleRoot() . '/common/view/datatable.fix.html.php';?>
<style>
body {margin-bottom: 25px;}
#mainMenu .btn-toolbar .btn-group .dropdown-menu .btn-active-text:hover .text {color: #fff;}
#mainMenu .btn-toolbar .btn-group .dropdown-menu .btn-active-text:hover .text:after {border-bottom: unset;}
.body-modal #mainMenu>.btn-toolbar {width: auto;}
</style>
<?php js::set('browseType', $browseType);?>
<?php js::set('productID', $productID);?>
<?php js::set('projectID', $projectID);?>
<?php js::set('branch', $branch);?>
<?php js::set('rawModule', $this->app->rawModule);?>
<?php js::set('productType', $this->app->tab == 'product' ? $product->type : '');?>
<?php
$unfoldStories = isset($config->product->browse->unfoldStories) ? json_decode($config->product->browse->unfoldStories, true) : array();
$unfoldStories = zget($unfoldStories, $productID, array());
js::set('unfoldStories', $unfoldStories);
js::set('unfoldAll', $lang->execution->treeLevel['all']);
js::set('foldAll', $lang->execution->treeLevel['root']);
js::set('storyType', $storyType);
$lang->story->createCommon = $storyType == 'story' ? $lang->story->createStory : $lang->story->createRequirement;
$isProjectStory = $this->app->rawModule == 'projectstory';
$projectIDParam = $isProjectStory ? "projectID=$projectID&" : '';
?>
<style>
.btn-group .icon-close:before {font-size: 5px; vertical-align: 25%;}
.btn-group a i.icon-plus, .btn-group a i.icon-link {font-size: 16px;}
.btn-group a.btn-secondary, .btn-group a.btn-primary {border-right: 1px solid rgba(255,255,255,0.2);}
.btn-group button.dropdown-toggle.btn-secondary, .btn-group button.dropdown-toggle.btn-primary {padding:6px;}
</style>
<div id="mainMenu" class="clearfix">
<div id="sidebarHeader">
<div class="title" title="<?php echo $moduleName;?>">
<?php
echo $moduleName;
if($moduleID and $moduleID !== 'all')
{
$removeLink = $browseType == 'bymodule' ? $this->createLink($this->app->rawModule, $this->app->rawMethod, $projectIDParam . "productID=$productID&branch=$branch&browseType=$browseType&param=0&storyType=$storyType&orderBy=$orderBy&recTotal=0&recPerPage={$pager->recPerPage}") : 'javascript:removeCookieByKey("storyModule")';
echo html::a($removeLink, "<i class='icon icon-sm icon-close'></i>", '', "class='text-muted'");
}
?>
</div>
</div>
<div class="btn-toolbar pull-left">
<?php
if(!commonModel::isTutorialMode())
{
foreach(customModel::getFeatureMenu($this->app->rawModule, $this->app->rawMethod) as $menuItem)
{
if(isset($menuItem->hidden)) continue;
if($menuItem->name == 'emptysr' && $storyType == 'story') continue;
$menuBrowseType = strpos($menuItem->name, 'QUERY') === 0 ? 'bySearch' : $menuItem->name;
if($menuItem->name == 'more')
{
if(!empty($lang->product->moreSelects))
{
$moreLabel = $lang->more;
$moreLabelActive = '';
$storyBrowseType = $this->session->storyBrowseType;
if(isset($lang->product->moreSelects[$storyBrowseType]))
{
$moreLabel = "<span class='text'>{$lang->product->moreSelects[$storyBrowseType]}</span> <span class='label label-light label-badge'>{$pager->recTotal}</span>";
$moreLabelActive = 'btn-active-text';
}
echo '<div class="btn-group" id="more">';
echo html::a('javascript:;', $moreLabel . " <span class='caret'></span>", '', "data-toggle='dropdown' class='btn btn-link $moreLabelActive'");
echo "<ul class='dropdown-menu'>";
foreach($lang->product->moreSelects as $key => $value)
{
$active = $key == $storyBrowseType ? 'btn-active-text' : '';
echo '<li>' . html::a($this->createLink($this->app->rawModule, $this->app->rawMethod, $projectIDParam . "productID=$productID&branch=$branch&browseType=$key&param=0&storyType=$storyType"), "<span class='text'>{$value}</span>", '', "class='btn btn-link $active'") . '</li>';
}
echo '</ul></div>';
}
}
elseif($menuItem->name == 'QUERY')
{
$searchBrowseLink = $this->createLink($this->app->rawModule, $this->app->rawMethod, $projectIDParam . "productID=$productID&branch=$branch&browseType=$menuBrowseType&param=%s&storyType=$storyType");
$isBySearch = $this->session->storyBrowseType == 'bysearch';
include $this->app->getModuleRoot() . '/common/view/querymenu.html.php';
}
else
{
$menuItemName = strtolower($menuItem->name);
echo html::a($this->createLink($this->app->rawModule, $this->app->rawMethod, $projectIDParam . "productID=$productID&branch=$branch&browseType=$menuBrowseType&param=0&storyType=$storyType"), "<span class='text'>$menuItem->text</span>" . ($menuItemName == $this->session->storyBrowseType ? ' <span class="label label-light label-badge">' . $pager->recTotal . '</span>' : ''), '', "id='{$menuItem->name}Tab' class='btn btn-link" . ($this->session->storyBrowseType == $menuItemName ? ' btn-active-text' : '') . "'");
}
}
}
?>
<a class="btn btn-link querybox-toggle" id='bysearchTab'><i class="icon icon-search muted"></i> <?php echo $lang->product->searchStory;?></a>
</div>
<?php if(!isonlybody()):?>
<div class="btn-toolbar pull-right">
<?php if($this->app->rawModule != 'projectstory') common::printIcon('story', 'report', "productID=$productID&branchID=$branch&storyType=$storyType&browseType=$browseType&moduleID=$moduleID&chartType=pie", '', 'button', 'bar-chart muted'); ?>
<div class="btn-group">
<button class="btn pull-right btn-link" data-toggle="dropdown"><i class="icon icon-export muted"></i> <span class="text"><?php echo $lang->export ?></span> <span class="caret"></span></button>
<ul class="dropdown-menu" id='exportActionMenu'>
<?php
$tab = $isProjectStory ? 'project' : 'product';
$class = common::hasPriv('story', 'export') ? '' : "class=disabled";
$misc = common::hasPriv('story', 'export') ? "data-toggle='modal' data-type='iframe' class='export' data-app='$tab'" : "class=disabled";
$link = common::hasPriv('story', 'export') ? $this->createLink('story', 'export', "productID=$productID&orderBy=$orderBy&projectID=0&browseType=$browseType&type=$storyType") : '#';
echo "<li $class>" . html::a($link, $lang->story->export, '', $misc) . "</li>";
?>
</ul>
</div>
<?php if(common::canModify('product', $product)):?>
<div class='btn-group dropdown'>
<?php
$createStoryLink = $this->createLink('story', 'create', "product=$productID&branch=$branch&moduleID=$moduleID&storyID=0&projectID=$projectID&bugID=0&planID=0&todoID=0&extra=&type=$storyType");
$batchCreateLink = $this->createLink('story', 'batchCreate', "productID=$productID&branch=$branch&moduleID=$moduleID&storyID=0&project=$projectID&plan=0&type=$storyType");
$buttonLink = '';
$buttonTitle = '';
$buttonType = $from == 'project' ? 'btn-secondary' : 'btn-primary';
if(common::hasPriv('story', 'batchCreate'))
{
$buttonLink = empty($productID) ? '' : $batchCreateLink;
$buttonTitle = $lang->story->batchCreate;
}
if(common::hasPriv('story', 'create'))
{
$buttonLink = $createStoryLink;
$buttonTitle = $lang->story->create;
}
$hidden = empty($buttonLink) ? 'hidden' : '';
echo html::a($buttonLink, "<i class='icon icon-plus'></i> $buttonTitle", '', "class='btn $buttonType $hidden create-story-btn' data-app='$tab'");
?>
<?php if(!empty($productID) and common::hasPriv('story', 'batchCreate') and common::hasPriv('story', 'create')): ?>
<button type='button' class="btn <?php echo $buttonType?> dropdown-toggle" data-toggle='dropdown'><span class='caret'></span></button>
<ul class='dropdown-menu pull-right'>
<li>
<?php
if(commonModel::isTutorialMode())
{
$wizardParams = helper::safe64Encode("productID=$productID&branch=$branch&moduleID=$moduleID");
if($isProjectStory) $wizardParams = helper::safe64Encode("productID=$productID&branch=$branch&moduleID=$moduleID&storyID=&projectID=$projectID");
$link = $this->createLink('tutorial', 'wizard', "module=story&method=create&params=$wizardParams");
echo html::a($link, $lang->story->createCommon, '', "data-app='$tab'");
}
else
{
echo html::a($createStoryLink, $lang->story->create, '', "data-group='$tab'");
}
?>
</li>
<li><?php echo html::a($batchCreateLink, $lang->story->batchCreate, '', "data-group='$tab'");?></li>
</ul>
<?php endif;?>
</div>
<?php endif;?>
</div>
<?php endif;?>
</div>
<?php if($this->app->getViewType() == 'xhtml'):?>
<div id="xx-title">
<strong>
<?php echo $this->product->getByID($productID)->name ?>
</strong>
<div class="linkButton" onclick="handleLinkButtonClick()">
<span title="<?php echo $lang->viewDetails;?>">
<i class="icon icon-import icon-rotate-270"></i>
</span>
</div>
</div>
<?php endif;?>
<div id="mainContent" class="main-row fade">
<div class="side-col" id="sidebar">
<div class="sidebar-toggle"><i class="icon icon-angle-left"></i></div>
<div class="cell">
<?php if(!$moduleTree):?>
<hr class="space">
<div class="text-center text-muted">
<?php echo $lang->product->noModule;?>
</div>
<hr class="space">
<?php endif;?>
<?php echo $moduleTree;?>
<div class="text-center">
<?php if($productID) common::printLink('tree', 'browse', "rootID=$productID&view=story&currentModuleID=0&branch=$branchID", $lang->tree->manageMenu, '', "class='btn btn-info btn-wide'");?>
<hr class="space-sm" />
</div>
</div>
</div>
<div class="main-col">
<div class="cell<?php if($browseType == 'bysearch') echo ' show';?>" id="queryBox" data-module='story'></div>
<?php if(empty($stories)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $storyType == 'story' ? $lang->story->noStory : $lang->story->noRequirement;?></span>
<?php if(common::canModify('product', $product) and common::hasPriv('story', 'create')):?>
<?php echo html::a($this->createLink('story', 'create', "productID={$productID}&branch={$branch}&moduleID={$moduleID}&storyID=0&projectID=$projectID&bugID=0&planID=0&todoID=0&extra=&type=$storyType"), "<i class='icon icon-plus'></i> " . $lang->story->createCommon, '', "class='btn btn-info' data-app='$from'");?>
<?php endif;?>
</p>
</div>
<?php else:?>
<form class="main-table table-story skip-iframe-modal" method="post" id='productStoryForm'>
<div class="table-header fixed-right">
<nav class="btn-toolbar pull-right"></nav>
</div>
<?php
$datatableId = $this->moduleName . ucfirst($this->methodName);
$useDatatable = (isset($config->datatable->$datatableId->mode) and $config->datatable->$datatableId->mode == 'datatable');
$vars = "productID=$productID&branch=$branch&browseType=$browseType&param=$param&storyType=$storyType&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}";
if($from == 'project') $vars = "projectID=$projectID&productID=$productID&branch=$branch&browseType=$browseType&param=$param&storyType=$storyType&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}";
if($useDatatable) include $this->app->getModuleRoot() . '/common/view/datatable.html.php';
$setting = $this->datatable->getSetting('product');
$widths = $this->datatable->setFixedFieldWidth($setting);
$columns = 0;
$canBeChanged = common::canModify('product', $product);
$canBatchEdit = ($canBeChanged and common::hasPriv('story', 'batchEdit'));
$canBatchClose = (common::hasPriv('story', 'batchClose') and strtolower($browseType) != 'closedbyme' and strtolower($browseType) != 'closedstory');
$canBatchReview = ($canBeChanged and common::hasPriv('story', 'batchReview'));
$canBatchChangeStage = ($canBeChanged and common::hasPriv('story', 'batchChangeStage'));
$canBatchChangeBranch = ($canBeChanged and common::hasPriv('story', 'batchChangeBranch'));
$canBatchChangeModule = ($canBeChanged and common::hasPriv('story', 'batchChangeModule'));
$canBatchChangePlan = ($canBeChanged and common::hasPriv('story', 'batchChangePlan'));
$canBatchAssignTo = ($canBeChanged and common::hasPriv('story', 'batchAssignTo'));
$canBatchUnlink = ($canBeChanged and $this->app->tab == 'project' and common::hasPriv('projectstory', 'batchUnlinkStory'));
$canBatchImportToLib = ($canBeChanged and $this->app->tab == 'project' and isset($this->config->maxVersion) and common::hasPriv('story', 'batchImportToLib'));
$canBatchAction = ($canBatchEdit or $canBatchClose or $canBatchReview or $canBatchChangeStage or $canBatchChangeModule or $canBatchChangePlan or $canBatchAssignTo or $canBatchUnlink or $canBatchImportToLib);
?>
<?php if(!$useDatatable) echo '<div class="table-responsive">';?>
<table class='table has-sort-head<?php if($useDatatable) echo ' datatable';?>' id='storyList' data-fixed-left-width='<?php echo $widths['leftWidth']?>' data-fixed-right-width='<?php echo $widths['rightWidth']?>'>
<thead>
<tr>
<?php if($this->app->getViewType() == 'xhtml'):?>
<?php
foreach($setting as $key => $value)
{
if($value->id == 'title' || $value->id == 'id' || $value->id == 'pri' || $value->id == 'status')
{
if($storyType == 'requirement' and (in_array($value->id, array('plan', 'stage')))) $value->show = false;
if($value->show)
{
$this->datatable->printHead($value, $orderBy, $vars, $canBatchAction);
$columns ++;
}
}
}?>
<?php else:?>
<?php
foreach($setting as $key => $value)
{
if($storyType == 'requirement' and (in_array($value->id, array('plan', 'stage')))) $value->show = false;
if($value->show)
{
$this->datatable->printHead($value, $orderBy, $vars, $canBatchAction);
$columns ++;
}
}
?>
<?php endif;?>
</tr>
</thead>
<tbody>
<?php foreach($stories as $story):?>
<tr data-id='<?php echo $story->id?>' data-estimate='<?php echo $story->estimate?>' data-cases='<?php echo zget($storyCases, $story->id, 0);?>'>
<?php $story->from = $from;?>
<?php if($this->app->getViewType() == 'xhtml'):?>
<?php
foreach($setting as $key => $value)
{
if($value->id == 'title' || $value->id == 'id' || $value->id == 'pri' || $value->id == 'status')
{
$this->story->printCell($value, $story, $users, $branchOption, $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table');
}
}?>
<?php else:?>
<?php foreach($setting as $key => $value) $this->story->printCell($value, $story, $users, $branchOption, $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table');?>
<?php endif;?>
</tr>
<?php if(!empty($story->children)):?>
<?php $i = 0;?>
<?php foreach($story->children as $key => $child):?>
<?php $child->from = $from;?>
<?php $class = $i == 0 ? ' table-child-top' : '';?>
<?php $class .= ($i + 1 == count($story->children)) ? ' table-child-bottom' : '';?>
<tr class='table-children<?php echo $class;?> parent-<?php echo $story->id;?>' data-id='<?php echo $child->id?>' data-status='<?php echo $child->status?>' data-estimate='<?php echo $child->estimate?>'>
<?php if($this->app->getViewType() == 'xhtml'):?>
<?php
foreach($setting as $key => $value)
{
if($value->id == 'title' || $value->id == 'id' || $value->id == 'pri' || $value->id == 'status')
{
$this->story->printCell($value, $child, $users, $branchOption, $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table', $storyType);
}
}?>
<?php else:?>
<?php foreach($setting as $key => $value) $this->story->printCell($value, $child, $users, $branchOption, $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table', $storyType);?>
<?php endif;?>
</tr>
<?php $i ++;?>
<?php endforeach;?>
<?php endif;?>
<?php endforeach;?>
</tbody>
</table>
<?php if(!$useDatatable) echo '</div>';?>
<div class="table-footer">
<?php if($canBatchAction):?>
<div class="checkbox-primary check-all"><label><?php echo $lang->selectAll?></label></div>
<?php endif;?>
<div class="table-actions btn-toolbar">
<div class='btn-group dropup'>
<?php
$disabled = $canBatchEdit ? '' : "disabled='disabled'";
$actionLink = $this->createLink('story', 'batchEdit', "productID=$productID&projectID=$projectID&branch=$branch&storyType=$storyType");
?>
<?php echo html::commonButton($lang->edit, "data-form-action='$actionLink' $disabled");?>
<button type='button' class='btn dropdown-toggle' data-toggle='dropdown'><span class='caret'></span></button>
<ul class='dropdown-menu'>
<?php
$class = $canBatchClose ? '' : "class='disabled'";
$actionLink = $this->createLink('story', 'batchClose', "productID=$productID&projectID=0&storyType=$storyType");
$misc = $canBatchClose ? "onclick=\"setFormAction('$actionLink', '', '#productStoryForm')\"" : '';
echo "<li $class>" . html::a('#', $lang->close, '', $misc) . "</li>";
if($canBatchReview)
{
echo "<li class='dropdown-submenu'>";
echo html::a('javascript:;', $lang->story->review, '', "id='reviewItem'");
echo "<ul class='dropdown-menu'>";
unset($lang->story->reviewResultList['']);
unset($lang->story->reviewResultList['revert']);
foreach($lang->story->reviewResultList as $key => $result)
{
$actionLink = $this->createLink('story', 'batchReview', "result=$key");
if($key == 'reject')
{
echo "<li class='dropdown-submenu'>";
echo html::a('#', $result, '', "id='rejectItem'");
echo "<ul class='dropdown-menu'>";
unset($lang->story->reasonList['']);
unset($lang->story->reasonList['subdivided']);
unset($lang->story->reasonList['duplicate']);
foreach($lang->story->reasonList as $key => $reason)
{
$actionLink = $this->createLink('story', 'batchReview', "result=reject&reason=$key");
echo "<li>";
echo html::a('#', $reason, '', "onclick=\"setFormAction('$actionLink', 'hiddenwin', '#productStoryForm')\"");
echo "</li>";
}
echo '</ul></li>';
}
else
{
echo '<li>' . html::a('#', $result, '', "onclick=\"setFormAction('$actionLink', 'hiddenwin', '#productStoryForm')\"") . '</li>';
}
}
echo '</ul></li>';
}
else
{
$class= "class='disabled'";
echo "<li $class>" . html::a('javascript:;', $lang->story->review, '', $class) . '</li>';
}
if($storyType == 'story')
{
if($canBatchChangeStage)
{
echo "<li class='dropdown-submenu'>";
echo html::a('javascript:;', $lang->story->stageAB, '', "id='stageItem'");
echo "<ul class='dropdown-menu'>";
foreach($lang->story->stageList as $key => $stage)
{
if(empty($key)) continue;
if(strpos('tested|verified|released|closed', $key) === false) continue;
$actionLink = $this->createLink('story', 'batchChangeStage', "stage=$key");
echo "<li>" . html::a('#', $stage, '', "onclick=\"setFormAction('$actionLink', 'hiddenwin', '#productStoryForm')\"") . "</li>";
}
echo '</ul></li>';
}
else
{
$class= "class='disabled'";
echo "<li $class>" . html::a('javascript:;', $lang->story->stageAB, '', $class) . '</li>';
}
}
?>
</ul>
</div>
<?php $isShowModuleBTN = ($this->app->tab == 'project' and $browseType != 'bybranch') ? false : true;?>
<?php if($canBatchChangeModule and $productID and $branchID !== 'all' and $isShowModuleBTN):?>
<div class="btn-group dropup">
<button data-toggle="dropdown" type="button" class="btn"><?php echo $lang->story->moduleAB;?> <span class="caret"></span></button>
<?php $withSearch = count($modules) > 8;?>
<div class="dropdown-menu search-list<?php if($withSearch) echo ' search-box-sink';?>" data-ride="searchList">
<?php if($withSearch):?>
<div class="input-control search-box has-icon-left has-icon-right search-example">
<input id="moduleSearchBox" type="search" autocomplete="off" class="form-control search-input">
<label for="moduleSearchBox" class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label>
<a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a>
</div>
<?php $modulesPinYin = common::convert2Pinyin($modules);
?>
<?php endif;?>
<div class="list-group">
<?php
foreach($modules as $moduleId => $module)
{
$searchKey = $withSearch ? ('data-key="' . zget($modulesPinYin, $module, '') . '"') : '';
$actionLink = $this->createLink('story', 'batchChangeModule', "moduleID=$moduleId");
echo html::a('#', empty($module) ? '/' : $module, '', "$searchKey onclick=\"setFormAction('$actionLink', 'hiddenwin', '#productStoryForm')\"");
}
?>
</div>
</div>
</div>
<?php endif;?>
<?php if($canBatchAssignTo):?>
<div class="btn-group dropup">
<button data-toggle="dropdown" type="button" class="btn"><?php echo $lang->story->assignedTo;?> <span class="caret"></span></button>
<?php
$withSearch = count($users) > 10;
$actionLink = $this->createLink('story', 'batchAssignTo', "productID=$productID");
echo html::select('assignedTo', $teamMembers, '', 'class="hidden"');
?>
<div class="dropdown-menu search-list<?php if($withSearch) echo ' search-box-sink';?>" data-ride="searchList">
<?php if($withSearch):?>
<?php $usersPinYin = common::convert2Pinyin($users);?>
<div class="input-control search-box has-icon-left has-icon-right search-example">
<input id="userSearchBox" type="search" autocomplete="off" class="form-control search-input">
<label for="userSearchBox" class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label>
<a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a>
</div>
<?php endif;?>
<div class="list-group">
<?php foreach ($teamMembers as $key => $value):?>
<?php
if(empty($key) or $key == 'closed') continue;
$searchKey = $withSearch ? ('data-key="' . zget($usersPinYin, $value, '') . " @$key\"") : "data-key='@$key'";
echo html::a("javascript:$(\"#assignedTo\").val(\"$key\");setFormAction(\"$actionLink\", \"hiddenwin\", \"#productStoryForm\")", $value, '', $searchKey);
?>
<?php endforeach;?>
</div>
</div>
</div>
<?php endif;?>
<?php if($canBatchImportToLib):?>
<?php echo html::a('#batchImportToLib', $lang->story->importToLib, '', 'class="btn" data-toggle="modal" id="importToLib"');?>
<?php endif;?>
</div>
<div class="table-statistic"><?php echo $summary;?></div>
<?php $pager->show('right', 'pagerjs');?>
</div>
</form>
<?php endif;?>
</div>
</div>
<div class="modal fade" id="linkStoryByPlan">
<div class="modal-dialog mw-500px">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="icon icon-close"></i></button>
<h4 class="modal-title"><?php echo $lang->execution->linkStoryByPlan;?></h4><?php echo '(' . $lang->project->linkStoryByPlanTips . ')';?>
</div>
<div class="modal-body">
<div class='input-group'>
<?php echo html::select('plan', zget($productPlans, $productID, ''), '', "class='form-control chosen' id='plan'");?>
<span class='input-group-btn'><?php echo html::commonButton($lang->execution->linkStory, "id='toTaskButton'", 'btn btn-primary');?></span>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="batchImportToLib">
<div class="modal-dialog mw-500px">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="icon icon-close"></i></button>
<h4 class="modal-title"><?php echo $lang->story->importToLib;?></h4>
</div>
<div class="modal-body">
<form method='post' class='form-ajax' action='<?php echo $this->createLink('story', 'batchImportToLib');?>'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->story->lib;?></th>
<td>
<?php echo html::select('lib', $libs, '', "class='form-control chosen' required");?>
</td>
</tr>
<?php if(!common::hasPriv('assetlib', 'approveStory') and !common::hasPriv('assetlib', 'batchApproveStory')):?>
<tr>
<th><?php echo $lang->story->approver;?></th>
<td>
<?php echo html::select('assignedTo', $approvers, '', "class='form-control chosen'");?>
</td>
</tr>
<?php endif;?>
<tr>
<td colspan='2' class='text-center'>
<?php echo html::hidden('storyIdList', '');?>
<?php echo html::submitButton($lang->import, '', 'btn btn-primary');?>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
</div>
<div class="modal fade" id="batchUnlinkStoryTip">
<div class="modal-dialog mw-700px">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="icon icon-close"></i></button>
<h4 class="modal-title"><strong><?php echo $lang->projectstory->batchUnlinkTip;?></strong></h4>
</div>
<div class="modal-body">
<table class='table'>
<thead>
<tr>
<th><?php echo $lang->story->title;?></th>
<th class='w-200px'><?php echo $lang->story->link . $lang->execution->common;?></th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan='2' class='text-center'>
<?php echo html::commonButton($lang->projectstory->confirm, 'data-dismiss="modal" id="confirmBtn"', 'btn btn-primary');?>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
<script>
var moduleID = <?php echo $moduleID?>;
var branchID = $.cookie('storyBranch');
$('#module<?php echo $moduleID;?>').closest('li').addClass('active');
$('#branch' + branchID).closest('li').addClass('active');
$(function()
{
// Update table summary text.
<?php $storyCommon = $storyType == 'requirement' ? $lang->URCommon : $lang->SRCommon;?>
var checkedSummary = '<?php echo str_replace('%storyCommon%', $storyCommon, $lang->product->checkedSummary)?>';
$('#productStoryForm').table(
{
statisticCreator: function(table)
{
var $checkedRows = table.getTable().find(table.isDataTable ? '.datatable-row-left.checked' : 'tbody>tr.checked');
var $originTable = table.isDataTable ? table.$.find('.datatable-origin') : null;
var checkedTotal = $checkedRows.length;
if(!checkedTotal) return;
var checkedEstimate = 0;
var checkedCase = 0;
$checkedRows.each(function()
{
var $row = $(this);
if ($originTable)
{
$row = $originTable.find('tbody>tr[data-id="' + $row.data('id') + '"]');
}
var data = $row.data();
checkedEstimate += data.estimate;
if(data.cases > 0) checkedCase += 1;
});
}
});
});
/**
* Set the color of the badge to white.
*
* @param object obj
* @param bool isShow
* @access public
* @return void
*/
function setBadgeStyle(obj, isShow)
{
var $label = $(obj);
if(isShow == true)
{
$label.find('.label-badge').css({"color":"#fff", "border-color":"#fff"});
}
else
{
$label.find('.label-badge').css({"color":"#838a9d", "border-color":"#838a9d"});
}
}
function handleLinkButtonClick()
{
var xxcUrl = "xxc:openInApp/zentao-integrated/" + encodeURIComponent(window.location.href.replace(/.display=card/, '').replace(/\.xhtml/, '.html'));
window.open(xxcUrl);
}
</script>
<?php include $this->app->getModuleRoot() . '/common/view/footer.html.php';?>
@@ -0,0 +1,36 @@
<?php
class project extends control
{
public function execution($status = 'all', $projectID = 0, $orderBy = 'order_asc', $productID = 0, $recTotal = 0, $recPerPage = 10, $pageID = 1)
{
$projectID = $this->project->saveState($projectID, $this->project->getPairsByProgram());
if($projectID == 0 and common::hasPriv('project', 'create')) $this->locate($this->createLink('project', 'create'));
if($projectID == 0 and !common::hasPriv('project', 'create')) $this->locate($this->createLink('project', 'browse'));
$this->project->setMenu($projectID);
$kanbanList = $this->loadModel('execution')->getList($projectID, 'all', $status);
$executionActions = array();
foreach($kanbanList as $kanbanID => $kanban)
{
foreach($this->config->execution->statusActions as $action)
{
if($this->execution->isClickable($kanban, $action)) $executionActions[$kanbanID][] = $action;
}
if($this->execution->isClickable($kanban, 'delete')) $executionActions[$kanbanID][] = 'delete';
}
$this->view->title = $this->lang->project->kanban;
$this->view->kanbanList = array_values($kanbanList);
$this->view->memberGroup = $this->execution->getMembersByIdList(array_keys($kanbanList));
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted');
$this->view->usersAvatar = $this->user->getAvatarPairs();
$this->view->projectID = $projectID;
$this->view->status = $status;
$this->view->executionActions = $executionActions;
$this->display();
}
}
@@ -0,0 +1,7 @@
$('#cards').on('click', '.panel', function(e)
{
if(!$(e.target).closest('.kanban-actions').length)
{
location.href = $(this).data('url');
}
});
@@ -0,0 +1,5 @@
<?php
$lang->project->leftStories = '剩余目标';
$lang->project->doingExecutions = '进行中的看板';
$lang->project->aclList['private'] = "私有 (只有项目负责人、团队成员可访问)";
@@ -0,0 +1,4 @@
<script>
$('#batchEditForm table thead tr th.c-parent').hide();
$('#batchEditForm table tbody tr td [name^="parents"]').closest('td').hide();
</script>
@@ -0,0 +1,26 @@
<?php
/**
* The prjbrowse view file of project module for lite vision of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Wenrui LI <liwenrui@easycorp.ltd>
* @package project
* @version $Id: prjbrowse.html.php 4769 2013-05-05 07:24:21Z wwccss $
* @link http://www.zentao.net
*/
?>
<?php include $this->app->getModuleRoot() . '/common/view/header.html.php';?>
<?php include $this->app->getModuleRoot() . '/common/view/datatable.fix.html.php';?>
<?php
js::set('orderBy', $orderBy);
js::set('programID', $programID);
js::set('browseType', $browseType);
js::set('param', $param);
js::set('orderBy', $orderBy);
js::set('recTotal', $recTotal);
js::set('recPerPage', $recPerPage);
js::set('pageID', $pageID);
?>
<?php include $this->app->getModuleRoot() . '/project/view/browsebylist.html.php';?>
<?php include $this->app->getModuleRoot() . '/common/view/footer.html.php';?>
@@ -0,0 +1,10 @@
<script>
$('#sidebarHeader').remove();
$('#sidebar').remove();
$('.panel-actions').remove();
$('.project-name').removeClass('has-prefix');
$('.project-type-label').remove();
$('.icon-project-manageProducts.icon-link').parent().remove();
$('.create-project-btn').attr('href', createLink('project', 'create', 'model=kanban')).removeAttr('data-toggle');
$('.table-empty-tip .btn').attr('href', createLink('project', 'create', 'model=kanban')).removeAttr('data-toggle');
</script>
@@ -0,0 +1,148 @@
<?php
/**
* The create view file of project module for lite vision of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Wenrui LI <liwenrui@easycorp.ltd>
* @package project
* @version $Id: create.html.php 4769 2013-05-05 07:24:21Z wwccss $
* @link http://www.zentao.net
*/
?>
<?php include $this->app->getModuleRoot() . 'common/view/header.html.php';?>
<?php include $this->app->getModuleRoot() . 'common/view/kindeditor.html.php';?>
<?php js::import($jsRoot . 'misc/date.js');?>
<?php js::set('model', $model);?>
<?php js::set('programID', $programID);?>
<?php js::set('copyProjectID', $copyProjectID);?>
<?php js::set('weekend', $config->execution->weekend);?>
<?php js::set('errorSameProducts', $lang->project->errorSameProducts);?>
<?php js::set('errorSameBranches', $lang->project->errorSameBranches);?>
<?php js::set('longTime', $lang->project->longTime);?>
<?php js::set('multiBranchProducts', $multiBranchProducts);?>
<?php js::set('selectedProductID', $productID);?>
<?php js::set('selectedBranchID', $branchID);?>
<?php $requiredFields = $config->project->create->requiredFields;?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->project->create;?></h2>
<?php if(!commonModel::isTutorialMode()): ?>
<div class="pull-right btn-toolbar">
<button type='button' class='btn btn-link' data-toggle='modal' data-target='#copyProjectModal'><?php echo html::icon($lang->icons['copy'], 'muted') . ' ' . $lang->project->copy;?></button>
</div>
<?php endif; ?>
</div>
<form class='form-indicator main-form form-ajax' method='post' target='hiddenwin' id='dataform'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->project->name;?></th>
<td class="col-main"><?php echo html::input('name', $name, "class='form-control' required");?></td>
</tr>
<tr>
<th><?php echo $lang->project->code;?></th>
<td><?php echo html::input('code', '', "class='form-control' required");?></td>
</tr>
<tr>
<th><?php echo $lang->project->PM;?></th>
<td><?php echo html::select('PM', $pmUsers, '', "class='form-control chosen'" . (strpos($requiredFields, 'PM') !== false ? ' required' : ''));?></td>
</tr>
<tr>
<th><?php echo $lang->project->budget;?></th>
<td>
<div class='input-group'>
<?php $placeholder = ($parentProgram and $parentProgram->budget != 0) ? 'placeholder=' . $lang->program->parentBudget . zget($lang->project->currencySymbol, $parentProgram->budgetUnit) . $availableBudget : '';?>
<?php echo html::input('budget', '', "class='form-control' maxlength='10' " . (strpos($requiredFields, 'budget') !== false ? 'required ' : '') . $placeholder);?>
<?php if($parentProgram):?>
<span class='input-group-addon'><?php echo zget($budgetUnitList, $parentProgram->budgetUnit);?></span>
<?php else:?>
<span class='input-group-addon'></span>
<?php echo html::select('budgetUnit', $budgetUnitList, $config->project->defaultCurrency, "class='form-control'");?>
<?php endif;?>
</div>
</td>
<td>
<div class='checkbox-primary'>
<input type='checkbox' id='future' name='future' value='1' />
<label for='future'><?php echo $lang->project->future;?></label>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->project->dateRange;?></th>
<td>
<div class='input-group'>
<?php echo html::input('begin', date('Y-m-d'), "class='form-control form-date' onchange='computeWorkDays();' placeholder='" . $lang->project->begin . "' required");?>
<span class='input-group-addon'><?php echo $lang->project->to;?></span>
<?php echo html::input('end', '', "class='form-control form-date' onchange='computeWorkDays();' placeholder='" . $lang->project->end . "' required");?>
</div>
</td>
<td colspan='2'><?php echo html::radio('delta', $lang->project->endList , '', "onclick='computeEndDate(this.value)'");?></td>
</tr>
<tr>
<th><?php echo $lang->project->desc;?></th>
<td colspan='3'>
<?php echo html::textarea('desc', '', "rows='6' class='form-control kindeditor' hidefocus='true'" . (strpos($requiredFields, 'desc') !== false ? ' required' : ''));?>
</td>
</tr>
<?php $this->printExtendFields('', 'table', 'columns=3');?>
<tr>
<th><?php echo $lang->project->acl;?></th>
<td colspan='3' class='aclBox'><?php echo nl2br(html::radio('acl', $lang->project->aclList, $acl, "onclick='setWhite(this.value);'", 'block'));?></td>
</tr>
<tr class="hidden" id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td colspan='2'>
<div class='input-group'>
<?php echo html::select('whitelist[]', $users, '', 'class="form-control chosen" multiple');?>
<?php echo $this->fetch('my', 'buildContactLists', "dropdownName=whitelist");?>
</div>
</td>
</tr>
<tr>
<td colspan='4' class='text-center form-actions'>
<?php
echo html::hidden('model', $model);
echo html::hidden('vision', 'lite');
echo html::hidden('parent', 0);
echo html::submitButton();
echo $gobackLink ? html::a($gobackLink, $lang->goback, '', 'class="btn btn-wide"') : html::backButton();
?>
</td>
</tr>
</table>
</form>
</div>
</div>
<div class='modal fade modal-scroll-inside' id='copyProjectModal'>
<div class='modal-dialog mw-900px'>
<div class='modal-header'>
<button type='button' class='close' data-dismiss='modal'><i class="icon icon-close"></i></button>
<h4 class='modal-title' id='myModalLabel'>
<?php echo $lang->project->copyTitle;?>
<?php echo html::input('projectName', '', "class='form-control' placeholder={$lang->project->searchByName}");?>
</h4>
</div>
<div class='modal-body'>
<?php if(empty($copyProjects)):?>
<div class='alert with-icon'>
<i class='icon-exclamation-sign'></i>
<div class='content'><?php echo $lang->project->copyNoProject;?></div>
</div>
<?php else:?>
<div id='copyProjects' class='row'>
<?php foreach ($copyProjects as $id => $name):?>
<?php $active = ($copyProjectID == $id) ? ' active' : '';?>
<div class='col-md-4 col-sm-6'><a href='javascript:;' data-id='<?php echo $id;?>' class='nobr <?php echo $active;?>'><?php echo html::icon($lang->icons['project'], 'text-muted') . ' ' . $name;?></a></div>
<?php endforeach;?>
</div>
<?php endif;?>
</div>
</div>
</div>
<div id='projectAcl' class='hidden'>
<?php echo nl2br(html::radio('acl', $lang->project->aclList, $acl, "onclick='setWhite(this.value);'", 'block'));?>
</div>
<?php include $this->app->getModuleRoot() . 'common/view/footer.html.php';?>
@@ -0,0 +1,7 @@
<script>
$('#dataform table tbody tr:first-child').hide();
$('#dataform table tbody tr:nth-child(5)').hide();
$('#dataform table tbody tr:nth-child(7)').hide();
$('#dataform table tbody tr:nth-child(8)').hide();
$('#dataform table tbody tr:nth-child(13)').hide();
</script>
@@ -0,0 +1,136 @@
<?php
/**
* The html template file of all method of execution module for lite vision of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Wenrui LI <liwenrui@easycorp.ltd>
* @package execution
* @version $Id: index.html.php 5094 2013-07-10 08:46:15Z chencongzhi520@gmail.com $
*/
?>
<?php include $this->app->getModuleRoot() . '/common/view/header.html.php';?>
<?php include $this->app->getModuleRoot() . '/common/view/sortable.html.php';?>
<div class='clearfix' id='mainMenu'>
<div class='btn-toolbar pull-left'>
<?php
foreach($lang->project->featureBar as $label => $labelName)
{
$active = $status == $label ? 'btn-active-text' : '';
echo html::a($this->createLink('project', 'execution', "status=$label&projectID=$projectID"), '<span class="text">' . $labelName . '</span> ' . ($status == $label ? "<span class='label label-light label-badge'>" . (int)count($kanbanList) . '</span>' : ''), '', "class='btn btn-link $active'");
}
?>
</div>
<div class='btn-toolbar pull-right'>
<?php common::printLink('execution', 'create', "projectID=$projectID", '<i class="icon icon-plus"></i> ' . $lang->project->createKanban, '', 'class="btn btn-primary"');?>
</div>
</div>
<div id='mainContent' class="main-row fade cell">
<?php if(empty($kanbanList)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->execution->noExecution;?></span>
<?php if(common::hasPriv('execution', 'create')):?>
<?php echo html::a($this->createLink('execution', 'create', "projectID=$projectID"), "<i class='icon icon-plus'></i> " . $lang->execution->createKanban, '', "class='btn btn-info' data-app='project'");?>
<?php endif;?>
</p>
</div>
<?php else:?>
<div class='kanban-cards'>
<?php foreach($kanbanList as $index => $kanban):?>
<div id="kanban-<?php echo $kanban->id;?>" class='kanban-card col' data-url='<?php echo $this->createLink('execution', 'kanban', "kanbanID=$kanban->id");?>'>
<div class="panel">
<div class="panel-heading">
<span class="label kanban-status-<?php echo $kanban->status;?>"><?php echo zget($lang->execution->statusList, $kanban->status);?></span>
<strong class="kanban-name" title='<?php echo $kanban->name;?>'><?php echo $kanban->name;?></strong>
<?php $canActions = (common::hasPriv('execution','edit') or (!empty($executionActions) and isset($executionActions[$kanban->id])));?>
<?php if($canActions):?>
<div class='kanban-actions kanban-actions<?php echo $kanban->id;?>'>
<div class='dropdown'>
<?php echo html::a('javascript:;', "<i class='icon icon-ellipsis-v'></i>", '', "data-toggle='dropdown' class='btn btn-link'");?>
<ul class='dropdown-menu <?php echo ($index + 1) % 4 == 0 ? 'pull-left' : 'pull-right';?>'>
<?php
if(common::hasPriv('execution','edit'))
{
$this->app->loadLang('kanban');
echo '<li>';
common::printLink('execution', 'edit', "executionID={$kanban->id}", '<i class="icon icon-edit"></i> ' . $lang->kanban->edit, '', "class='iframe' data-width='75%'", '', true);
echo '</li>';
}
if(!empty($executionActions[$kanban->id]))
{
if(in_array('start', $executionActions[$kanban->id])) echo '<li>' . html::a(helper::createLink('execution', 'start', "executionID={$kanban->id}", '', true), '<i class="icon icon-play"></i>' . $lang->execution->start, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('putoff', $executionActions[$kanban->id])) echo '<li>' . html::a(helper::createLink('execution', 'putoff', "executionID=$kanban->id", '', true), '<i class="icon icon-calendar"></i>' . $lang->execution->putoff, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('suspend', $executionActions[$kanban->id])) echo '<li>' . html::a(helper::createLink('execution', 'suspend', "executionID=$kanban->id", '', true), '<i class="icon icon-pause"></i>' . $lang->execution->suspend, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('close', $executionActions[$kanban->id])) echo '<li>' . html::a(helper::createLink('execution', 'close', "executionID=$kanban->id", '', true), '<i class="icon icon-off"></i>' . $lang->execution->close, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('activate', $executionActions[$kanban->id])) echo '<li>' . html::a(helper::createLink('execution', 'activate', "executionID=$kanban->id", '', true), '<i class="icon icon-magic"></i>' . $lang->execution->activate, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('delete', $executionActions[$kanban->id])) echo '<li>' . html::a(helper::createLink('execution', 'delete', "executionID=$kanban->id&confirm=no&kanban=yes", '', true), '<i class="icon icon-trash"></i>' . $lang->kanban->delete, '', "target='hiddenwin'") . '</li>';
}?>
</ul>
</div>
</div>
<?php endif;?>
</div>
<div class="panel-body">
<div class="kanban-desc">
<?php echo $kanban->desc;?>
</div>
<div class="kanban-footer">
<div class='kanban-members pull-left'>
<?php $teams = $memberGroup[$kanban->id];?>
<?php foreach($teams as $member):?>
<div title="<?php echo zget($users, $member->account);?>">
<?php echo html::smallAvatar(array('avatar' => zget($usersAvatar, $member->account), 'account' => $member->account)); ?>
</div>
<?php endforeach;?>
</div>
<div class='kanban-members-count pull-left'><?php echo sprintf($lang->project->teamSumCount, count($teams));?></div>
<div class='kanban-acl pull-right'>
<span><i class="icon icon-<?php echo $kanban->acl == 'private' ? 'lock' : 'unlock-alt';?>"></i> <?php echo zget($lang->project->acls, $kanban->acl, '');?></span>
</div>
</div>
</div>
</div>
</div>
<?php endforeach;?>
</div>
<?php endif;?>
</div>
<style>
.kanban-cards {padding-top: 12px; width: 100%;}
.kanban-card {width: 25%;}
.kanban-card .panel {margin: 0 0; border: 1px solid #DCDCDC; border-radius: 4px; box-shadow: none; cursor: pointer; height: 160px; margin-bottom: 5px;}
.kanban-card .panel:hover {border-color: #006AF1; box-shadow: 0 0 10px 0 rgba(0,0,100,.25);}
.kanban-card .panel:hover .kanban-actions {visibility: unset;}
.kanban-card .kanban-actions {position: absolute; top: 2px; right: 2px; float: right; visibility: hidden;}
.kanban-card .kanban-actions .dropdown-menu.pull-right {top:31px; right: -84px; left: auto;}
.kanban-card .kanban-actions .dropdown-menu.pull-left {top:31px; right:-1px; left: auto;}
.kanban-card .kanban-desc {color: #838a9d; word-break:break-all; height: 70px; overflow: hidden; display: -webkit-box; float:left;}
.kanban-card .kanban-footer {position: absolute; bottom: 10px; right: 10px; left: 15px;}
.kanban-card .kanban-members {float: left; height: 24px; line-height: 24px;}
.kanban-card .kanban-members > div {display: inline-block; height: 24px;}
.kanban-card .kanban-members > div + div {margin-left: -5px;}
.kanban-card .kanban-members > div > .avatar {display: inline-block; width: 24px; height: 24px; line-height: 24px; margin-right: 1px;}
.kanban-card .kanban-members > span {display: inline-block; color: transparent; width: 2px; height: 2px; background-color: #8990a2; position: relative; border-radius: 50%; top: 3px; margin: 0 3px;}
.kanban-card .kanban-members > span:before,
.kanban-card .kanban-members > span:after {content: ''; display: block; position: absolute; width: 2px; height: 2px; background-color: #8990a2; top: 0; border-radius: 50%}
.kanban-card .kanban-members > span:before {left: -4px;}
.kanban-card .kanban-members > span:after {right: -4px;}
.kanban-card .kanban-members-count {display: inline-block; margin-left: 6px; position: relative; top: 3px}
.kanban-card .kanban-acl {position: absolute; right: 0px; bottom: 2px; color: #838a9d;}
.kanban-card .label.kanban-status-wait {background-color: #E5E5E5; color: #808080;}
.kanban-card .label.kanban-status-doing {background-color: #DDF4DF; color: #38B03F;}
.kanban-card .label.kanban-status-suspended {background-color: #FFF0D5; color: #F1A325;}
.kanban-card .label.kanban-status-closed {background-color: #808080; color: #FFF;}
</style>
<script>
/* Make cards clickable. */
$('.kanban-cards').on('click', '.kanban-card', function(e)
{
if(!$(e.target).closest('.kanban-actions').length)
{
window.location.href = $(this).data('url');
}
});
</script>
<?php include $this->app->getModuleRoot() . '/common/view/footer.html.php';?>
@@ -0,0 +1,4 @@
<style>
.kanban-lane-name {background-color: transparent !important;}
.kanban-lane-name span.text{display:none;}
</style>
@@ -0,0 +1,145 @@
<?php include $this->app->getModuleRoot() . 'common/view/header.html.php';?>
<?php js::set('projectID', $project->id);?>
<?php js::set('roles', $roles);?>
<?php js::set('deptID', $dept);?>
<?php js::set('pickerUsers', $userInfoList);?>
<?php js::set('copyProjectID', $copyProjectID);?>
<?php js::set('oldAccountList', array_keys($currentMembers));?>
<?php js::set('unlinkExecutionMembers', $lang->project->unlinkExecutionMembers);?>
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<span class='btn btn-link btn-active-text'>
<?php echo html::a($this->createLink('project', 'managemembers', "projectID={$project->id}"), "<span class='text'> {$lang->project->manageMembers}</span>");?>
</span>
<div class='input-group space w-200px'>
<span class='input-group-addon'><?php echo $lang->execution->selectDept?></span>
<?php echo html::select('dept', $depts, $dept, "class='form-control chosen' onchange='setDeptUsers(this)' data-placeholder='{$lang->execution->selectDeptTitle}'");?>
<?php if(count($teams2Import) > 1):?>
<span class='input-group-addon'><?php echo $lang->execution->copyTeam;?></span>
<?php echo html::select('project', $teams2Import, $copyProjectID, "class='form-control chosen' onchange='choseTeam2Copy(this)' data-placeholder='{$lang->project->copyTeamTitle}'");?>
<?php endif;?>
</div>
</div>
</div>
<div id='mainContent' class='main-content'>
<form class='main-form form-ajax' method='post' id='teamForm'>
<table class='table table-form'>
<thead>
<tr class='text-center'>
<th><?php echo $lang->team->account;?></th>
<th><?php echo $lang->team->role;?></th>
<th class='c-days hidden'><?php echo $lang->team->days;?></th>
<th class='c-hours hidden'><?php echo $lang->team->hours;?></th>
<th class='c-limited hidden'><?php echo $lang->team->limited;?></th>
<th class="c-actions"><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
<?php $i = 0;?>
<?php foreach($currentMembers as $member):?>
<?php if(!isset($users[$member->account])) continue;?>
<?php unset($users[$member->account]);?>
<tr>
<td><?php echo html::input("realnames[$i]", $member->realname, "class='form-control' readonly");?></td>
<td><?php echo html::input("roles[$i]", $member->role, "class='form-control'");?></td>
<td class='hidden'><?php echo html::input("days[$i]", $member->days, "class='form-control'");?></td>
<td class='hidden'><?php echo html::input("hours[$i]", $member->hours, "class='form-control'");?></td>
<td class='hidden'><?php echo html::radio("limited[$i]", $lang->team->limitedList, $member->limited);?></td>
<td class='c-actions text-center'>
<?php echo html::hidden("accounts[$i]", $member->account);?>
<?php echo html::a('javascript:;', "<i class='icon-plus'></i>", '', "onclick='addItem(this)' class='btn btn-link'");?>
<?php echo html::a('javascript:;', "<i class='icon icon-close'></i>", '', "onclick='deleteItem(this)' class='btn btn-link'");?>
</td>
</tr>
<?php $i ++;?>
<?php endforeach;?>
<?php foreach($deptUsers as $deptAccount => $userName):?>
<?php if(!isset($users[$deptAccount])) continue;?>
<tr class='addedItem'>
<td><?php echo html::select("accounts[$i]", $users, $deptAccount, "class='form-control chosen' onchange='setRole(this.value, $i)'");?></td>
<td><?php echo html::input("roles[$i]", $roles[$deptAccount], "class='form-control'");?></td>
<td class='hidden'><?php echo html::input("days[$i]", $project->days, "class='form-control'");?></td>
<td class='hidden'><?php echo html::input("hours[$i]", $config->execution->defaultWorkhours, "class='form-control'");?></td>
<td class='hidden'><?php echo html::radio("limited[$i]", $lang->team->limitedList, 'no');?></td>
<td class='c-actions text-center'>
<?php echo html::a('javascript:;', "<i class='icon-plus'></i>", '', "onclick='addItem(this)' class='btn btn-link'");?>
<?php echo html::a('javascript:;', "<i class='icon icon-close'></i>", '', "onclick='deleteItem(this)' class='btn btn-link'");?>
</td>
</tr>
<?php unset($users[$deptAccount]);?>
<?php $i ++;?>
<?php endforeach;?>
<?php foreach($members2Import as $member2Import):?>
<?php if(!isset($users[$member2Import->account])) continue;?>
<tr class='addedItem'>
<td><?php echo html::select("accounts[$i]", $users, $member2Import->account, "class='form-control user-picker' onchange='setRole(this.value, $i)'");?></td>
<td><?php echo html::input("roles[$i]", $member2Import->role, "class='form-control'");?></td>
<td class='hidden'><?php echo html::input("days[$i]", $project->days, "class='form-control'");?></td>
<td class='hidden'><?php echo html::input("hours[$i]", $member2Import->hours, "class='form-control'");?></td>
<td class='hidden'><?php echo html::radio("limited[$i]", $lang->team->limitedList, 'no');?></td>
<td class='c-actions text-center'>
<?php echo html::a('javascript:;', "<i class='icon-plus'></i>", '', "onclick='addItem(this)' class='btn btn-link'");?>
<?php echo html::a('javascript:;', "<i class='icon icon-close'></i>", '', "onclick='deleteItem(this)' class='btn btn-link'");?>
</td>
</tr>
<?php unset($users[$member2Import->account]);?>
<?php $i ++;?>
<?php endforeach;?>
<?php for($j = 0; $j < 5; $j ++):?>
<tr class='addedItem'>
<td><?php echo html::select("accounts[$i]", $users, '', "class='form-control user-picker' onchange='setRole(this.value, $i)'");?></td>
<td><?php echo html::input("roles[$i]", '', "class='form-control'");?></td>
<td class='hidden'><?php echo html::input("days[$i]", $project->days, "class='form-control'");?></td>
<td class='hidden'><?php echo html::input("hours[$i]", $config->execution->defaultWorkhours, "class='form-control'");?></td>
<td class='hidden'><?php echo html::radio("limited[$i]", $lang->team->limitedList, 'no');?></td>
<td class='c-actions text-center'>
<?php echo html::a('javascript:;', "<i class='icon-plus'></i>", '', "onclick='addItem(this)' class='btn btn-link'");?>
<?php echo html::a('javascript:;', "<i class='icon icon-close'></i>", '', "onclick='deleteItem(this)' class='btn btn-link'");?>
</td>
</tr>
<?php $i ++;?>
<?php endfor;?>
</tbody>
<tfoot>
<tr>
<td colspan='3' class='text-center form-actions'>
<?php
echo html::hidden('removeExecution', 'no');
if(commonModel::isTutorialMode())
{
echo html::submitButton($lang->save, '', 'btn btn-wide btn-primary');
}
else
{
echo html::submitButton('', '', 'hidden btn btn-wide btn-primary');
echo html::commonButton($lang->save, 'onclick="saveMembers()" id="saveBtn"', 'btn btn-wide btn-primary');
}
echo html::backButton();
?>
</td>
</tr>
</tfoot>
</table>
<?php js::set('i', $i);?>
</form>
</div>
<div>
<?php $i = '%i%';?>
<table class='hidden'>
<tr id='addItem' class='hidden'>
<td><?php echo html::select("accounts[$i]", $users, '', "class='form-control' onchange='setRole(this.value, $i)'");?></td>
<td><?php echo html::input("roles[$i]", '', "class='form-control'");?></td>
<td class='hidden'><?php echo html::input("days[$i]", $project->days, "class='form-control'");?></td>
<td class='hidden'><?php echo html::input("hours[$i]", $config->execution->defaultWorkhours, "class='form-control'");?></td>
<td class='hidden'><?php echo html::radio("limited[$i]", $lang->team->limitedList, 'no');?></td>
<td class='c-actions text-center'>
<?php echo html::a('javascript:;', "<i class='icon-plus'></i>", '', "onclick='addItem(this)' class='btn btn-link'");?>
<?php echo html::a('javascript:;', "<i class='icon icon-close'></i>", '', "onclick='deleteItem(this)' class='btn btn-link'");?>
</td>
</tr>
</table>
</div>
<?php include $this->app->getModuleRoot() . 'common/view/footer.html.php';?>
@@ -0,0 +1,96 @@
<?php
/**
* The team view file of project module of ZenTaoPMS.
*
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Qiyu Xie
* @package project
* @version $Id: team.html.php 4143 2021-08-11 11:01:06Z $
* @link https://www.zentao.net
*/
?>
<?php include $this->app->getModuleRoot() . 'common/view/header.html.php';?>
<?php js::set('confirmUnlinkMember', $lang->project->confirmUnlinkMember)?>
<?php js::set('noAccess', $lang->user->error->noAccess)?>
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<span class='btn btn-link btn-active-text'><span class='text'><?php echo $lang->project->teamMember;?></span></span>
</div>
<div class='btn-toolbar pull-right'>
<?php
if($canBeChanged)
{
if(commonModel::isTutorialMode())
{
$wizardParams = helper::safe64Encode("projectID=$projectID");
echo html::a($this->createLink('tutorial', 'wizard', "module=project&method=manageMembers&params=$wizardParams"), "<i class='icon icon-persons'></i> " . $lang->project->manageMembers, '', "class='btn btn-primary manage-team-btn'");
}
else
{
if(!empty($app->user->admin) or empty($app->user->rights['rights']['my']['limited'])) common::printLink('project', 'manageMembers', "projectID=$projectID", "<i class='icon icon-persons'></i> " . $lang->project->manageMembers, '', "class='btn btn-primary manage-team-btn'");
}
}
?>
</div>
</div>
<div id='mainContent'>
<?php if(empty($teamMembers)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->execution->noMembers;?></span>
<?php if((!empty($app->user->admin) or empty($app->user->rights['rights']['my']['limited'])) && common::hasPriv('project', 'manageMembers')):?>
<?php echo html::a($this->createLink('project', 'manageMembers', "projectID=$projectID"), "<i class='icon icon-persons'></i> " . $lang->project->manageMembers, '', "class='btn btn-info'");?>
<?php endif;?>
</p>
</div>
<?php else:?>
<form class='main-table'>
<table class='table' id='memberList'>
<thead>
<tr>
<th><?php echo $lang->team->account;?></th>
<th><?php echo $lang->team->role;?></th>
<?php if($canBeChanged):?>
<th class='c-actions-1 w-80px text-center'><?php echo $lang->actions;?></th>
<?php endif;?>
</tr>
</thead>
<tbody>
<?php $totalHours = 0;?>
<?php foreach($teamMembers as $member):?>
<tr>
<td>
<?php
if(common::hasPriv('user', 'view'))
{
$link = isset($deptUsers[$member->userID]) ? $this->createLink('user', 'view', "userID={$member->userID}") : "javascript: alert(noAccess);";
echo html::a($link, $member->realname, '', 'data-app="system"');
}
else
{
echo $member->realname;
}
$memberHours = $member->days * $member->hours;
$totalHours += $memberHours;
?>
</td>
<td title='<?php echo $member->role;?>'><?php echo $member->role;?></td>
<?php if($canBeChanged):?>
<td class='c-actions text-center'>
<?php
if (common::hasPriv('project', 'unlinkMember', $member))
{
echo html::a("javascript:deleteMemeber($projectID, \"{$member->account}\", \"{$member->userID}\")", '<i class="icon-green-project-unlinkMember icon-unlink"></i>', '', "class='btn' title='{$lang->project->unlinkMember}'");
}
?>
</td>
<?php endif;?>
</tr>
<?php endforeach;?>
</tbody>
</table>
</form>
<?php endif;?>
</div>
<?php include $this->app->getModuleRoot() . 'common/view/footer.html.php';?>
@@ -0,0 +1,5 @@
<script>
$('.side-col .row .cell .detail').addClass('hidden');
$('.side-col .row .cell .detail:first').removeClass('hidden');
$('.side-col .row .cell .detail:last').removeClass('hidden');
</script>
@@ -0,0 +1,8 @@
<?php
class projectStory extends control
{
public function story($projectID = 0, $productID = 0, $branch = 0, $browseType = '', $param = 0, $storyType = 'story', $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
echo $this->fetch('product', 'browse', "productID=$productID&branch=$branch&browseType=$browseType&param=$param&storyType=$storyType&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID&projectID=$projectID");
}
}
@@ -0,0 +1,6 @@
<?php
unset($lang->projectstory->featureBar['story']['changed']);
unset($lang->projectstory->featureBar['story']['linkedExecution']);
unset($lang->projectstory->featureBar['story']['unlinkedExecution']);
$lang->projectstory->featureBar['story']['closedstory'] = $lang->projectstory->featureBar['story']['closed'];
unset($lang->projectstory->featureBar['story']['closed']);
+13
View File
@@ -0,0 +1,13 @@
<?php
unset($config->search->fields->bug);
unset($config->search->fields->product);
unset($config->search->fields->build);
unset($config->search->fields->case);
unset($config->search->fields->productplan);
unset($config->search->fields->release);
unset($config->search->fields->testtask);
unset($config->search->fields->testsuite);
unset($config->search->fields->effort);
unset($config->search->fields->caselib);
unset($config->search->fields->testreport);
unset($config->search->fields->program);
@@ -0,0 +1,17 @@
<?php
$lang->search->modules['task'] = '任务';
$lang->search->modules['execution'] = '看板';
$lang->search->modules['story'] = '目标';
unset($lang->search->modules['case']);
unset($lang->search->modules['bug']);
unset($lang->search->modules['build']);
unset($lang->search->modules['effort']);
unset($lang->search->modules['caselib']);
unset($lang->search->modules['product']);
unset($lang->search->modules['release']);
unset($lang->search->modules['testtask']);
unset($lang->search->modules['testsuite']);
unset($lang->search->modules['testreport']);
unset($lang->search->modules['productplan']);
unset($lang->search->modules['program']);
+21
View File
@@ -0,0 +1,21 @@
<?php
$config->story->list->exportFields = '
id, module, title, spec, verify, keywords,
pri, estimate, status,
openedBy, openedDate, assignedTo, assignedDate, mailto,
reviewedBy, reviewedDate,
closedBy, closedDate, closedReason,
lastEditedBy, lastEditedDate,
childStories, linkStories, duplicateStory, files';
$config->story->datatable->defaultField = array('id', 'pri', 'title', 'openedBy', 'assignedTo', 'estimate', 'status', 'actions');
unset($config->story->datatable->fieldList['plan']);
unset($config->story->datatable->fieldList['source']);
unset($config->story->datatable->fieldList['sourceNote']);
unset($config->story->datatable->fieldList['stage']);
unset($config->story->datatable->fieldList['category']);
unset($config->story->datatable->fieldList['feedbackBy']);
unset($config->story->datatable->fieldList['notifyEmail']);
unset($config->story->datatable->fieldList['bugCount']);
unset($config->story->datatable->fieldList['caseCount']);
@@ -0,0 +1,8 @@
<?php
$lang->story->module = '所属目录';
$lang->story->parent = '父目标';
$lang->story->legendSpec = '目标描述';
$lang->story->children = '子目标';
$lang->story->legendLifeTime = '目标的一生';
$lang->story->legendProjectAndTask = '看板任务';
+10
View File
@@ -0,0 +1,10 @@
<?php
public function getExecutionStoryPairs($executionID = 0, $productID = 0, $branch = 'all', $moduleIdList = 0, $type = 'full', $status = 'all')
{
if($this->config->vision == 'lite')
{
$execution = $this->loadModel('execution')->getById($executionID);
if($execution->project) $executionID = $execution->project;
}
return parent::getExecutionStoryPairs($executionID, $productID, $branch, $moduleIdList, $type, $status);
}
@@ -0,0 +1,141 @@
<?php
/**
* The batch create view of story module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yangyang Shi <shiyangyang@cnezsoft.com>
* @package story
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include $this->app->getModuleRoot() . 'common/view/header.html.php';?>
<div id="mainContent" class="main-content">
<div class="main-header">
<h2><?php echo $storyID ? $storyTitle . ' - ' . $this->lang->story->subdivide : $this->lang->story->batchCreate;?></h2>
<div class="pull-right btn-toolbar">
<?php if(common::hasPriv('file', 'uploadImages')) echo html::a($this->createLink('file', 'uploadImages', 'module=story&params=' . helper::safe64Encode("productID=$productID&branch=$branch&moduleID=$moduleID&storyID=$storyID&executionID=&plan=&type=$type")), $lang->uploadImages, '', "data-toggle='modal' data-type='iframe' class='btn btn-primary' data-width='70%'")?>
<button type='button' data-toggle='modal' data-target="#importLinesModal" class="btn btn-primary"><?php echo $lang->pasteText;?></button>
</div>
</div>
<?php
$visibleFields = array();
$requiredFields = array();
foreach(explode(',', $showFields) as $field)
{
if($field) $visibleFields[$field] = '';
}
foreach(explode(',', $config->story->create->requiredFields) as $field)
{
if($field)
{
$requiredFields[$field] = '';
if(strpos(",{$config->story->list->customBatchCreateFields},", ",{$field},") !== false) $visibleFields[$field] = '';
}
}
unset($visibleFields['module']);
?>
<form method='post' class='load-indicator main-form' enctype='multipart/form-data' target='hiddenwin' id="batchCreateForm">
<div class="table-responsive">
<table class="table table-form">
<thead>
<tr>
<th class='c-module<?php echo zget($requiredFields, 'module', '', ' required');?>'><?php echo $lang->story->module;?></th>
<th class='c-name required has-btn'><?php echo $lang->story->title;?></th>
<th class='c-spec<?php echo zget($visibleFields, 'spec', ' hidden') . zget($requiredFields, 'spec', '', ' required');?>'><?php echo $lang->story->spec;?></th>
<th class='c-pri<?php echo zget($requiredFields, 'pri', '', ' required');?>'><?php echo $lang->story->pri;?></th>
<th class='c-estimate<?php echo zget($requiredFields, 'estimate', '', ' required');?>'><?php echo $lang->story->estimate;?></th>
<th style="width: 200px !important"><?php echo $lang->story->reviewedBy;?></th>
<th class='c-keywords<?php echo zget($requiredFields, 'keywords', '', ' required');?>'><?php echo $lang->story->keywords;?></th>
<?php
$extendFields = $this->story->getFlowExtendFields();
foreach($extendFields as $extendField) echo "<th class='c-extend'>{$extendField->name}</th>";
?>
</tr>
</thead>
<tbody>
<tr class="template">
<td class='text-left' style='overflow:visible'><?php echo html::select('module[$id]', $moduleOptionMenu, $moduleID, "class='form-control chosen'");?></td>
<td style='overflow:visible'>
<div class="input-group">
<div class="input-control has-icon-right">
<input type="text" name="title[$id]" id="title$id" value="" class="form-control title-import input-story-title" autocomplete="off">
<div class="colorpicker">
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown"><span class="cp-title"></span><span class="color-bar"></span><i class="ic"></i></button>
<ul class="dropdown-menu clearfix">
<li class="heading"><?php echo $lang->story->colorTag;?><i class="icon icon-close"></i></li>
</ul>
<input type="hidden" class="colorpicker" id="color$id" name="color[$id]" value="" data-icon="color" data-wrapper="input-control-icon-right" data-update-color="#title$id">
</div>
</div>
<span class="input-group-btn">
<button type="button" class="btn btn-link btn-icon btn-copy" data-copy-from="#title$id" data-copy-to="#spec$id" title="<?php echo $lang->story->copyTitle;?>"><i class="icon icon-arrow-right"></i></button>
</span>
</div>
</td>
<td class='<?php echo zget($visibleFields, 'spec', 'hidden')?>'><textarea name="spec[$id]" id="spec$id" rows="1" class="form-control autosize"></textarea></td>
<td class='text-left<?php echo zget($visibleFields, 'pri', ' hidden')?>' style='overflow:visible'><?php echo html::select('pri[$id]', $priList, $pri, "class='form-control chosen'");?></td>
<td><?php echo html::input('estimate[$id]', $estimate, "class='form-control'");?></td>
<td><?php echo html::select('reviewer[$id][]', $reviewers, '', "class='form-control chosen' multiple");?></td>
<td><?php echo html::input('keywords[$id]', '', "class='form-control'");?></td>
<?php foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->loadModel('flow')->getFieldControl($extendField, '', $extendField->field . '[$id]') . "</td>";?>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="7" class="text-center form-actions">
<?php echo html::submitButton($lang->save);?>
<?php echo html::backButton();?>
</td>
</tr>
</tfoot>
</table>
</div>
</form>
</div>
<script>
$(function()
{
var imageTitles = <?php echo empty($titles) ? '""' : json_encode($titles);?>;
var storyTitles = <?php echo empty($titles) ? '""' : json_encode(array_keys($titles));?>;
$('#batchCreateForm').batchActionForm(
{
idEnd: <?php echo max((empty($titles) ? 0 : count($titles)), 9)?>,
rowCreator: function($row, index)
{
$row.find('select.chosen,select.picker-select').each(function()
{
var $select = $(this);
if($select.hasClass('picker-select')) $select.parent().find('.picker').remove();
if(index == 0) $select.find("option[value='ditto']").remove();
if(index > 0) $select.val('ditto');
if($select.attr('id').indexOf('branch') >= 0) $select.val('<?php echo $branch;?>')
$select.chosen();
setTimeout(function()
{
$select.next('.chosen-container').find('.chosen-drop').width($select.closest('td').width() + 50);
}, 200);
});
var storyTitle = storyTitles && storyTitles[index];
if (storyTitle !== undefined && storyTitle !== null)
{
$row.find('.input-story-title').val(storyTitle).after('<input type="hidden" name="uploadImage[' + index + ']" id="uploadImage[' + index + ']" value="' + imageTitles[storyTitle] + '">');
}
}
});
$(document).on('change', "#mainContent select[name^=needReview]", function()
{
select = $(this).parent('td').next('td').children("select[name^=reviewer]");
$(select).removeAttr('disabled');
if($(this).val() == 0) $(select).attr('disabled', 'disabled');
$(select).trigger("chosen:updated");
})
});
</script>
<?php if(isset($execution)) js::set('execution', $execution);?>
<?php js::set('storyType', $type);?>
<?php include $this->app->getModuleRoot() . 'common/view/pastetext.html.php';?>
<?php include $this->app->getModuleRoot() . 'common/view/footer.html.php';?>
@@ -0,0 +1,116 @@
<?php
/**
* The batch edit view of story module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Congzhi Chen <congzhi@cnezsoft.com>
* @package story
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include $this->app->getModuleRoot() . 'common/view/header.html.php';?>
<?php js::set('dittoNotice', $this->lang->story->dittoNotice);?>
<?php js::set('storyType', $storyType);?>
<?php js::set('app', $this->app->tab);?>
<?php if(isset($resetActive)) js::set('resetActive', true);?>
<div class='main-content' id='mainContent'>
<div class='main-header'>
<h2>
<?php echo $lang->story->common . $lang->colon . $lang->story->batchEdit;?>
</h2>
</div>
<?php if(isset($suhosinInfo)):?>
<div id='suhosinInfo' class='alert alert-info'><?php echo $suhosinInfo;?></div>
<?php else:?>
<form method='post' target='hiddenwin' action="<?php echo inLink('batchEdit', "productID=$productID&executionID=$executionID")?>" id="batchEditForm">
<div class="table-responsive">
<table class='table table-form'>
<thead>
<tr>
<th class='c-id'> <?php echo $lang->idAB;?></th>
<th class='c-module'><?php echo $lang->story->module;?></th>
<th class='c-title required'><?php echo $lang->story->title;?></th>
<th class='c-estimate'> <?php echo $lang->story->estimateAB;?></th>
<th class='c-pri'> <?php echo $lang->priAB;?></th>
<th class='c-user'> <?php echo $lang->story->assignedTo;?></th>
<th class='c-status'><?php echo $lang->story->status;?></th>
<th class='c-stage'> <?php echo $lang->story->stageAB;?></th>
<th class='c-user-box'><?php echo $lang->story->closedBy;?></th>
<th class='c-reason'> <?php echo $lang->story->closedReason;?></th>
<th class='c-keywords'><?php echo $lang->story->keywords;?></th>
<?php
$extendFields = $this->story->getFlowExtendFields();
foreach($extendFields as $extendField) echo "<th class='c-extend'>{$extendField->name}</th>";
?>
</tr>
</thead>
<tbody>
<?php foreach($stories as $storyID => $story):?>
<tr>
<td><?php echo $storyID . html::hidden("storyIdList[$storyID]", $storyID);?></td>
<td class='text-left'>
<?php echo html::select("modules[$storyID]", isset($modules[$story->product][$story->branch]) ? $modules[$story->product][$story->branch] : array('0' => '/'), $story->module, "class='form-control chosen'");?>
</td>
<td title='<?php echo $story->title?>'>
<div class="input-group">
<div class="input-control has-icon-right">
<?php echo html::input("", $story->title, "class='form-control input-story-title' disabled"); ?>
<?php echo html::hidden("titles[$storyID]", $story->title); ?>
<div class="colorpicker">
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown"><span class="cp-title"></span><span class="color-bar"></span><i class="ic"></i></button>
<ul class="dropdown-menu clearfix">
<li class="heading"><?php echo $lang->story->colorTag;?><i class="icon icon-close"></i></li>
</ul>
<?php echo html::hidden("colors[$storyID]", $story->color, "class='colorpicker' data-wrapper='input-control-icon-right' data-icon='color' data-btn-tip='{$lang->story->colorTag}' data-update-color='#titles\\[{$storyID}\\]'");?>
</div>
</div>
</div>
</td>
<td><?php echo html::input("estimates[$storyID]", $story->estimate, "class='form-control'"); ?></td>
<td><?php echo html::select("pris[$storyID]", $priList, $story->pri, 'class=form-control');?></td>
<td class='text-left'><?php echo html::select("assignedTo[$storyID]", $users, $story->assignedTo, "class='form-control chosen'");?></td>
<td class='story-<?php echo $story->status;?>'><?php echo $this->processStatus('story', $story);?></td>
<td><?php echo html::select("stages[$storyID]", $stageList, $story->stage, 'class="form-control"' . ($story->status == 'draft' ? ' disabled="disabled"' : ''));?></td>
<td class='text-left'><?php echo html::select("closedBys[$storyID]", $users, $story->closedBy, "class='form-control" . ($story->status == 'closed' ? " chosen'" : "' disabled='disabled'"));?></td>
<?php if($story->status == 'closed'):?>
<td>
<table class='w-p100'>
<tr>
<td class='pd-0'>
<?php echo html::select("closedReasons[$storyID]", $reasonList, $story->closedReason, "class=form-control onchange=setDuplicateAndChild(this.value,$storyID) style='min-width: 70px'");?>
</td>
<td class='pd-0' id='<?php echo 'duplicateStoryBox' . $storyID;?>' <?php if($story->closedReason != 'duplicate') echo "style='display: none'";?>>
<?php echo html::input("duplicateStoryIDList[$storyID]", '', "class='form-control' placeholder='{$lang->idAB}'");?>
</td>
<td class='pd-0' id='<?php echo 'childStoryBox' . $storyID;?>' <?php if($story->closedReason != 'subdivided') echo "style='display: none'";?>>
<?php echo html::input("childStoriesIDList[$storyID]", '', "class='form-control' placeholder='{$lang->idAB}'");?>
</td>
</tr>
</table>
</td>
<?php else:?>
<td><?php echo html::select("closedReasons[$storyID]", $reasonList, $story->closedReason, 'class="form-control" disabled="disabled"');?></td>
<?php endif;?>
<td><?php echo html::input("keywords[$storyID]", $story->keywords, 'class="form-control"');?></td>
<?php foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow: visible'" : '') . ">" . $this->loadModel('flow')->getFieldControl($extendField, $story, $extendField->field . "[{$storyID}]") . "</td>";?>
</tr>
<?php endforeach;?>
</tbody>
<tfoot>
<tr>
<td colspan='11' class='text-center form-actions'>
<?php echo html::submitButton();?>
<?php echo $this->app->tab == 'product' ? html::a($this->session->storyList, $lang->goback, '', "class='btn btn-back btn-wide'") : html::backButton();?>
</td>
</tr>
</tfoot>
</table>
</div>
</form>
<?php endif;?>
<?php include $this->app->getModuleRoot() . 'common/view/footer.html.php';?>
@@ -0,0 +1,6 @@
<script>
$("a[href^='#affectedBugs']").parent().remove();
$("a[href^='#affectedCases']").parent().remove();
$("#mainContent").find("#verify").closest("tr").addClass("hide");
$("#mainContent").find("#affectedProjects").closest("tr").addClass("hide");
</script>
@@ -0,0 +1,9 @@
<script>
$('#closedReason option').each(function()
{
if($(this).val() != '' && $(this).val() != 'done' && $(this).val() != 'duplicate' && $(this).val() != 'cancel')
{
$(this).remove();
}
})
</script>
@@ -0,0 +1,195 @@
<?php
/**
* The create view of story module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package story
* @version $Id: create.html.php 4902 2013-06-26 05:25:58Z wyd621@gmail.com $
* @link http://www.zentao.net
*/
?>
<?php include $this->app->getModuleRoot() . 'common/view/header.html.php';?>
<?php include $this->app->getModuleRoot() . 'common/view/kindeditor.html.php';?>
<?php js::set('page', 'create');?>
<?php js::set('holders', $lang->story->placeholder); ?>
<?php js::set('blockID', $blockID); ?>
<?php js::set('feedbackSource', $config->story->feedbackSource); ?>
<?php js::set('storyType', $type);?>
<?php if(common::checkNotCN()):?>
<style> .sourceTd > .input-group > .input-group > .input-group-addon:first-child{padding: 5px 18px} </style>
<?php endif;?>
<div id="mainContent" class="main-content">
<div class="center-block">
<div class="main-header">
<h2><?php echo $lang->story->create;?></h2>
</div>
<form class="load-indicator main-form form-ajax" method='post' enctype='multipart/form-data' id='dataform'>
<table class="table table-form">
<tbody>
<tr>
<th><?php echo $lang->story->module;?></th>
<td>
<div class='input-group' id='moduleIdBox'>
<?php
echo html::select('module', $moduleOptionMenu, $moduleID, "class='form-control chosen'");
if(count($moduleOptionMenu) == 1)
{
echo "<div class='input-group-addon'>";
echo html::a($this->createLink('tree', 'browse', "rootID=$productID&view=story&currentModuleID=0&branch=$branch", '', true), $lang->tree->manage, '', "class='text-primary' data-toggle='modal' data-type='iframe' data-width='90%'");
echo '&nbsp; ';
echo html::a("javascript:void(0)", $lang->refresh, '', "class='refresh' onclick='loadProductModules($productID)'");
echo '</div>';
}
?>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->story->reviewedBy;?></th>
<td colspan='<?php echo $type == 'story' ? 4 : 2;?>' id='reviewerBox'>
<div class="table-row">
<div class="table-col">
<?php echo html::select('reviewer[]', $reviewers, empty($needReview) ? $product->PO : '', "class='form-control chosen' multiple");?>
</div>
<?php if(!$this->story->checkForceReview()):?>
<div class="table-col w-130px">
<span class="input-group-addon" style="border: 1px solid #dcdcdc; border-left-width: 0px;">
<div class='checkbox-primary'>
<input id='needNotReview' name='needNotReview' value='1' type='checkbox' class='no-margin' <?php echo $needReview;?>/>
<label for='needNotReview'><?php echo $lang->story->needNotReview;?></label>
</div>
</span>
</div>
<?php endif;?>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->story->title;?></th>
<td colspan="4">
<div class='table-row'>
<div class='table-col'>
<div class="input-control has-icon-right">
<?php echo html::input('title', $storyTitle, "class='form-control' required");?>
<div class="colorpicker">
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown"><span class="cp-title"></span><span class="color-bar"></span><i class="ic"></i></button>
<ul class="dropdown-menu clearfix">
<li class="heading"><?php echo $lang->story->colorTag;?><i class="icon icon-close"></i></li>
</ul>
<input type="hidden" class="colorpicker" id="color" name="color" value="" data-icon="color" data-wrapper="input-control-icon-right" data-update-color="#title" data-provide="colorpicker">
</div>
</div>
</div>
<div class='table-col w-120px'>
<div class="input-group">
<span class="input-group-addon fix-border br-0"><?php echo $lang->story->pri;?></span>
<?php
$hasCustomPri = false;
foreach($lang->story->priList as $priKey => $priValue)
{
if(!empty($priKey) and (string)$priKey != (string)$priValue)
{
$hasCustomPri = true;
break;
}
}
$priList = $lang->story->priList;
if(end($priList)) unset($priList[0]);
if(!isset($priList[$pri]))
{
reset($priList);
$pri = key($priList);
}
?>
<?php if($hasCustomPri):?>
<?php echo html::select('pri', (array)$priList, $pri, "class='form-control'");?>
<?php else:?>
<div class="input-group-btn pri-selector" data-type="pri">
<button type="button" class="btn dropdown-toggle br-0" data-toggle="dropdown">
<span class="pri-text"><span class="label-pri label-pri-<?php echo empty($pri) ? '0' : $pri?>" title="<?php echo $pri?>"><?php echo $pri?></span></span> &nbsp;<span class="caret"></span>
</button>
<div class='dropdown-menu pull-right'>
<?php echo html::select('pri', (array)$priList, $pri, "class='form-control' data-provide='labelSelector' data-label-class='label-pri'");?>
</div>
</div>
<?php endif;?>
</div>
</div>
<div class='table-col w-120px'>
<div class="input-group">
<span class="input-group-addon fix-border br-0"><?php echo $lang->story->estimateAB;?></span>
<input type="text" name="estimate" id="estimate" value="<?php echo $estimate;?>" class="form-control" autocomplete="off" placeholder='<?php echo $lang->story->hour;?>' />
</div>
</div>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->story->spec;?></th>
<td colspan="4">
<?php echo $this->fetch('user', 'ajaxPrintTemplates', 'type=story&link=spec');?>
<?php echo html::textarea('spec', $spec, "rows='9' class='form-control kindeditor disabled-ie-placeholder' hidefocus='true' placeholder='" . htmlSpecialString($lang->noticePasteImg) . "'");?>
</td>
</tr>
<tr class='hide'>
<th><?php echo $lang->story->status;?></th>
<td><?php echo html::hidden('status', 'draft');?></td>
</tr>
<?php $this->printExtendFields('', 'table', 'columns=4');?>
<tr>
<th><?php echo $lang->story->legendAttatch;?></th>
<td colspan='4'><?php echo $this->fetch('file', 'buildform');?></td>
</tr>
<tr>
<th><?php echo $lang->story->mailto;?></th>
<td colspan="4">
<div class="input-group">
<?php echo html::select('mailto[]', $users, str_replace(' ' , '', $mailto), "class='form-control chosen' data-placeholder='{$lang->chooseUsersToMail}' multiple");?>
<?php echo $this->fetch('my', 'buildContactLists');?>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->story->keywords;?></th>
<td colspan="4">
<?php echo html::input('keywords', $keywords, 'class="form-control"');?>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" class="text-center form-actions">
<?php echo html::hidden('type', $type) . html::submitButton();?>
<?php echo html::hidden('product', $productID);?>
<?php echo html::hidden('plan', $planID);?>
<?php echo html::hidden('vision', 'lite');?>
<?php echo html::backButton();?>
</td>
</tr>
</tfoot>
</table>
</form>
</div>
</div>
<?php js::set('executionID', $objectID);?>
<?php js::set('storyModule', $lang->story->module);?>
<?php js::set('storyType', $type);?>
<script>
$(function(){parent.$('body.hide-modal-close').removeClass('hide-modal-close');})
function loadProductModules(productID)
{
var branch = 0;
var currentModule = 0;
var moduleLink = createLink('tree', 'ajaxGetOptionMenu', 'productID=' + productID + '&viewtype=story&branch=' + branch + '&rootModuleID=0&returnType=html&fieldID=&needManage=true&extra=&currentModuleID=' + currentModule);
var $moduleIDBox = $('#moduleIdBox');
$moduleIDBox.load(moduleLink, function()
{
$moduleIDBox.find('#module').chosen();
});
}
</script>
<?php include $this->app->getModuleRoot() . '/common/view/footer.html.php';?>
+191
View File
@@ -0,0 +1,191 @@
<?php
/**
* The edit view file of story module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package story
* @version $Id: edit.html.php 4645 2013-04-11 08:32:09Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
?>
<?php include $this->app->getModuleRoot() . 'common/view/header.html.php';?>
<?php include $this->app->getModuleRoot() . 'common/view/kindeditor.html.php';?>
<?php js::set('page', 'edit')?>
<?php js::set('oldProductID', $story->product);?>
<?php js::set('parentStory', !empty($story->children));?>
<?php js::set('moveChildrenTips', $lang->story->moveChildrenTips);?>
<?php js::set('rawModule', $this->app->rawModule);?>
<?php js::set('reviewedReviewer', $reviewedReviewer);?>
<?php js::set('storyModule', $lang->story->module);?>
<?php js::set('reviewers', explode(',', $reviewers));?>
<?php js::set('reviewerNotEmpty', $lang->story->notice->reviewerNotEmpty);?>
<?php js::set('feedbackSource', $config->story->feedbackSource); ?>
<div class='main-content' id='mainContent'>
<form method='post' enctype='multipart/form-data' target='hiddenwin' id='dataform'>
<div class='main-header'>
<h2>
<span class='label label-id'><?php echo $story->id;?></span>
<?php echo html::a($this->createLink('story', 'view', "storyID=$story->id"), $story->title, '', 'class="story-title"');?>
<small><?php echo $lang->arrow . ' ' . $lang->story->edit;?></small>
</h2>
</div>
<div class='main-row'>
<div class='main-col col-8'>
<div class='cell'>
<div class='form-group'>
<div class="input-control has-icon-right">
<div class="colorpicker">
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown" title="<?php echo $lang->task->colorTag ?>"><span class="cp-title"></span><span class="color-bar"></span><i class="ic"></i></button>
<ul class="dropdown-menu clearfix">
<li class="heading"><?php echo $lang->story->colorTag;?><i class="icon icon-close"></i></li>
</ul>
<input type="hidden" class="colorpicker" id="color" name="color" value="<?php echo $story->color ?>" data-icon="color" data-wrapper="input-control-icon-right" data-update-color=".story-title" data-provide="colorpicker">
</div>
<?php echo html::input('title', $story->title, 'class="form-control disabled story-title" disabled="disabled"');?>
</div>
</div>
<div class='detail'>
<div class='detail-title'><?php echo $lang->story->legendSpec;?></div>
<div class='detail-content article-content'><?php echo $story->spec;?></div>
</div>
<?php $this->printExtendFields($story, 'div', 'position=left');?>
<div class='detail'>
<div class='detail-title'><?php echo $lang->story->comment;?></div>
<div class='form-group'>
<?php echo html::textarea('comment', '', "rows='5' class='form-control'");?>
</div>
</div>
<div class='actions form-actions text-center'>
<?php
echo html::hidden('lastEditedDate', $story->lastEditedDate);
echo html::hidden('product', $story->product);
echo html::submitButton($lang->save);
if(!isonlybody()) echo html::backButton();
?>
</div>
<hr class='small' />
<?php include $this->app->getModuleRoot() . 'common/view/action.html.php';?>
</div>
</div>
<div class='side-col col-4'>
<div class='cell'>
<div class='detail'>
<div class='detail-title'><?php echo $lang->story->legendBasicInfo;?></div>
<table class='table table-form'>
<tr>
<th class='thWidth'><?php echo $lang->story->module;?></th>
<td>
<div class='input-group' id='moduleIdBox'>
<?php
echo html::select('module', $moduleOptionMenu, $story->module, "class='form-control chosen'");
if(count($moduleOptionMenu) == 1)
{
echo "<span class='input-group-addon'>";
echo html::a($this->createLink('tree', 'browse', "rootID=$story->product&view=story&currentModuleID=0&branch=$story->branch", '', true), $lang->tree->manage, '', "class='text-primary' data-toggle='modal' data-type='iframe' data-width='95%'");
echo '&nbsp; ';
echo html::a("javascript:void(0)", $lang->refresh, '', "class='refresh' onclick='loadProductModules($story->product)'");
echo '</span>';
}
?>
</div>
</td>
</tr>
<?php if($story->parent >= 0 and $story->type == 'story'):?>
<tr>
<th><?php echo $lang->story->parent;?></th>
<td><?php echo html::select('parent', $stories, $story->parent, "class='form-control chosen'");?></td>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->story->status;?></th>
<td>
<span class='story-<?php echo $story->status;?>'><?php echo $this->processStatus('story', $story);?></span>
<?php echo html::hidden('status', $story->status);?>
</td>
</tr>
<tr>
<th><?php echo $lang->story->pri;?></th>
<td><?php echo html::select('pri', $lang->story->priList, $story->pri, "class='form-control chosen'");?></td>
</tr>
<tr>
<th><?php echo $lang->story->estimate;?></th>
<td><?php echo $story->parent >= 0 ? html::input('estimate', $story->estimate, "class='form-control'") : $story->estimate;?></td>
</tr>
<tr class='feedbackBox <?php echo in_array($story->source, $config->story->feedbackSource) ? '' : 'hidden';?>'>
<th><?php echo $lang->story->feedbackBy;?></th>
<td><?php echo html::input('feedbackBy', $story->feedbackBy, "class='form-control'");?></td>
</tr>
<tr class='feedbackBox <?php echo in_array($story->source, $config->story->feedbackSource) ? '' : 'hidden';?>'>
<th><?php echo $lang->story->notifyEmail;?></th>
<td><?php echo html::input('notifyEmail', $story->notifyEmail, "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->story->keywords;?></th>
<td><?php echo html::input('keywords', $story->keywords, "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->story->mailto;?></th>
<td>
<div class='input-group'>
<?php echo html::select('mailto[]', $users, str_replace(' ' , '', $story->mailto), "class='form-control chosen' multiple");?>
<?php echo $this->fetch('my', 'buildContactLists');?>
</div>
</td>
</tr>
</table>
</div>
<div class='detail'>
<div class='detail-title'><?php echo $lang->story->legendLifeTime;?></div>
<table class='table table-form'>
<tr>
<th class='thWidth'><?php echo $lang->story->openedBy;?></th>
<td><?php echo zget($users, $story->openedBy);?></td>
</tr>
<tr>
<th><?php echo $lang->story->assignedTo;?></th>
<td><?php echo html::select('assignedTo', $users, $story->assignedTo, 'class="form-control chosen"');?></td>
</tr>
<?php if($isShowReviewer):?>
<tr>
<th><?php echo $lang->story->reviewers;?></th>
<td><?php echo html::select('reviewer[]', $productReviewers, $reviewers, 'class="form-control chosen" multiple')?></td>
</tr>
<?php endif;?>
<?php if($story->status == 'closed'):?>
<tr>
<th><?php echo $lang->story->closedBy;?></th>
<td><?php echo html::select('closedBy', $users, $story->closedBy, 'class="form-control chosen"');?></td>
</tr>
<tr>
<th><?php echo $lang->story->closedReason;?></th>
<td><?php echo html::select('closedReason', $lang->story->reasonList, $story->closedReason, "class='form-control' onchange='setStory(this.value)'");?></td>
</tr>
<?php endif;?>
</table>
</div>
<?php $this->printExtendFields($story, 'div', 'position=right');?>
</div>
</div>
</div>
</form>
</div>
<?php js::set('storyType', $story->type);?>
<?php js::set('executionID', isset($objectID) ? $objectID : 0);?>
<script>
function loadProductModules(productID)
{
var branch = 0;
var currentModule = $('#module').val();
var moduleLink = createLink('tree', 'ajaxGetOptionMenu', 'productID=' + productID + '&viewtype=story&branch=' + branch + '&rootModuleID=0&returnType=html&fieldID=&needManage=true&extra=&currentModuleID=' + currentModule);
var $moduleIDBox = $('#moduleIdBox');
$moduleIDBox.load(moduleLink, function()
{
$moduleIDBox.find('#module').chosen();
});
}
</script>
<?php include $this->app->getModuleRoot() . 'common/view/footer.html.php';?>
@@ -0,0 +1,4 @@
<script>
$("a[href^='#affectedBugs']").parent().remove();
$("a[href^='#affectedCases']").parent().remove();
</script>
+359
View File
@@ -0,0 +1,359 @@
<?php
/**
* The view file of story module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package story
* @version $Id: view.html.php 4952 2013-07-02 01:14:58Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
?>
<?php include $this->app->getModuleRoot() . 'common/view/header.html.php';?>
<?php include $this->app->getModuleRoot() . 'common/view/kindeditor.html.php';?>
<?php $browseLink = $app->session->storyList ? $app->session->storyList : $this->createLink('product', 'browse', "productID=$story->product");?>
<?php js::set('sysurl', common::getSysUrl());?>
<?php if(strpos($_SERVER["QUERY_STRING"], 'isNotice=1') === false):?>
<div id="mainMenu" class="clearfix">
<?php if($this->app->getViewType() == 'xhtml'):?>
<div class="linkButton" onclick="handleLinkButtonClick()">
<span title="<?php echo $lang->viewDetails;?>">
<i class="icon icon-import icon-rotate-270"></i>
</span>
</div>
<?php endif;?>
<div class="btn-toolbar pull-left">
<?php if(!isonlybody()):?>
<?php echo html::a($browseLink, '<i class="icon icon-back icon-sm"></i> ' . $lang->goback, '', "class='btn btn-secondary'");?>
<div class="divider"></div>
<?php endif;?>
<div class="page-title">
<span class="label label-id"><?php echo $story->id?></span>
<span class="text" title='<?php echo $story->title;?>' style='color: <?php echo $story->color;?>'>
<?php if($story->parent > 0) echo '<span class="label label-badge label-primary no-margin">' . $this->lang->story->childrenAB . '</span>';?>
<?php if($story->parent > 0) echo isset($story->parentName) ? html::a(inlink('view', "storyID={$story->parent}"), $story->parentName) . ' / ' : '';?><?php echo $story->title;?>
</span>
<?php if($story->version > 1):?>
<small class='dropdown'>
<a href='#' data-toggle='dropdown' class='text-muted'><?php echo '#' . $version;?> <span class='caret'></span></a>
<ul class='dropdown-menu'>
<?php
for($i = $story->version; $i >= 1; $i --)
{
$class = $i == $version ? " class='active'" : '';
echo '<li' . $class .'>' . html::a(inlink('view', "storyID=$story->id&version=$i"), '#' . $i) . '</li>';
}
?>
</ul>
</small>
<?php endif; ?>
<?php if($story->deleted):?>
<span class='label label-danger'><?php echo $lang->story->deleted;?></span>
<?php endif; ?>
</div>
</div>
<?php if(!isonlybody()):?>
<div class="btn-toolbar pull-right">
<?php if(common::canModify('product', $product)): ?>
<?php
$otherParam = 'storyID=&projectID=';
if($this->app->rawModule == 'projectstory') $otherParam = "storyID=&projectID={$this->session->project}";
?>
<?php common::printLink('story', 'create', "productID={$story->product}&branch={$story->branch}&moduleID={$story->module}&$otherParam&bugID=0&planID=0&todoID=0&extra=&type=$story->type", "<i class='icon icon-plus'></i> " . $lang->story->create, '', "class='btn btn-primary' data-app='project'"); ?>
<?php endif;?>
</div>
<?php endif;?>
</div>
<?php if($this->app->getViewType() == 'xhtml'):?>
<div id="scrollContent">
<?php endif;?>
<?php endif;?>
<div id="mainContent" class="main-row">
<div class="main-col col-8">
<div class="cell">
<div class="detail">
<div class="detail-title"><?php echo $lang->story->legendSpec;?></div>
<div class="detail-content article-content"><?php echo $story->spec;?></div>
</div>
<?php echo $this->fetch('file', 'printFiles', array('files' => $story->files, 'fieldset' => 'true', 'object' => $story));?>
<?php
$canBeChanged = common::canBeChanged('story', $story);
if($canBeChanged) $actionFormLink = $this->createLink('action', 'comment', "objectType=story&objectID=$story->id");
?>
<?php if(!empty($story->children)):?>
<div class='detail'>
<div class='detail-title'><?php echo $this->lang->story->children;?></div>
<div class='detail-content article-content'>
<table class='table table-hover table-fixed'>
<thead>
<tr class='text-center'>
<th class='w-50px'> <?php echo $lang->story->id;?></th>
<th class='w-40px'> <?php echo $lang->priAB;?></th>
<th> <?php echo $lang->story->title;?></th>
<th class='w-100px'><?php echo $lang->story->assignedTo;?></th>
<th class='w-90px'> <?php echo $lang->story->estimate;?></th>
<th class='w-80px'> <?php echo $lang->story->status;?></th>
<th class='w-230px'><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
<?php foreach($story->children as $child):?>
<tr class='text-center'>
<td><?php echo $child->id;?></td>
<td>
<?php
echo "<span class='pri-" . $child->pri . "'>";
echo $child->pri == '0' ? '' : zget($this->lang->story->priList, $child->pri, $child->pri);
echo "</span>";
?>
</td>
<td class='text-left' title='<?php echo $child->title;?>'><a class="iframe" data-width="90%" href="<?php echo $this->createLink('story', 'view', "storyID=$child->id", '', true); ?>"><?php echo $child->title;?></a></td>
<td><?php echo zget($users, $child->assignedTo);?></td>
<td title="<?php echo $child->estimate . ' ' . $lang->hourCommon;?>"><?php echo $child->estimate . $config->hourUnit;?></td>
<td><?php echo $this->processStatus('story', $child);?></td>
<td class='c-actions'>
<?php
common::printIcon('story', 'change', "storyID=$child->id", $child, 'list', 'alter');
common::printIcon('story', 'review', "storyID=$child->id", $child, 'list', 'search', '', 'iframe showinonlybody', true);
common::printIcon('story', 'assignTo', "storyID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true);
common::printIcon('story', 'close', "storyID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true);
common::printIcon('story', 'activate', "storyID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true);
common::printIcon('story', 'edit', "storyID=$child->id", $child, 'list');
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</div>
</div>
<?php endif;?>
</div>
<?php $this->printExtendFields($story, 'div', "position=left&inForm=0&inCell=1");?>
<?php if($this->app->getViewType() != 'xhtml'):?>
<div class="cell"><?php include $this->app->getModuleRoot() . 'common/view/action.html.php';?></div>
<?php endif;?>
<div class='main-actions'>
<div class="btn-toolbar">
<?php common::printBack($browseLink);?>
<?php if(!isonlybody()) echo "<div class='divider'></div>";?>
<?php if(!$story->deleted):?>
<?php
common::printIcon('story', 'change', "storyID=$story->id", $story, 'button', 'alter', '', 'showinonlybody');
common::printIcon('story', 'review', "storyID=$story->id", $story, 'button', 'search', '', 'showinonlybody');
if($story->status == 'active' and $story->stage == 'wait' and $story->parent <= 0 and !isonlybody())
{
$divideLang = $lang->story->subdivide;
$misc = "class='btn divideStory' data-toggle='modal' data-type='iframe' data-width='95%'";
$link = $this->createLink('story', 'batchCreate', "productID=$story->product&branch=$story->branch&moduleID=$story->module&storyID=$story->id", '', true);
if(common::hasPriv('story', 'batchCreate', $story)) echo html::a($link, "<i class='icon icon-split'></i> " . $divideLang, '', $misc);
}
common::printIcon('story', 'assignTo', "storyID=$story->id", $story, 'button', '', '', 'iframe showinonlybody', true);
common::printIcon('story', 'close', "storyID=$story->id", $story, 'button', '', '', 'iframe showinonlybody', true);
common::printIcon('story', 'activate', "storyID=$story->id", $story, 'button', '', '', 'iframe showinonlybody', true);
if(isset($this->config->maxVersion) and $this->app->tab == 'project' and common::hasPriv('story', 'importToLib')) echo html::a('#importToLib', "<i class='icon icon-assets'></i> " . $this->lang->story->importToLib, '', 'class="btn" data-toggle="modal"');
if($from == 'execution' and strpos('draft,closed', $story->status) === false) common::printIcon('task', 'create', "execution=$param&storyID=$story->id&moduleID=$story->module", $story, 'button', 'plus', '', 'showinonlybody');
echo $this->buildOperateMenu($story, 'view');
echo "<div class='divider'></div>";
common::printIcon('story', 'edit', "storyID=$story->id", $story);
common::printIcon('story', 'create', "productID=$story->product&branch=$story->branch&moduleID=$story->module&storyID=$story->id&executionID=0&bugID=0&planID=0&todoID=0&extra=&type=$story->type", $story, 'button', 'copy', '', '', '', "data-width='1050'");
common::printIcon('story', 'delete', "storyID=$story->id", $story, 'button', 'trash', 'hiddenwin');
?>
<?php endif;?>
</div>
</div>
</div>
<div class="side-col col-4">
<div class="cell">
<div class='tabs'>
<ul class='nav nav-tabs'>
<li class='active'><a href='#legendBasicInfo' data-toggle='tab'><?php echo $lang->story->legendBasicInfo;?></a></li>
<li><a href='#legendLifeTime' data-toggle='tab'><?php echo $lang->story->legendLifeTime;?></a></li>
</ul>
<div class='tab-content'>
<div class='tab-pane active' id='legendBasicInfo'>
<table class="table table-data">
<tbody>
<tr class='w-90px'>
<th><?php echo $lang->story->module;?></th>
<?php
$moduleTitle = '';
ob_start();
if(empty($modulePath))
{
$moduleTitle .= '/';
echo "/";
}
else
{
if($storyModule->branch and isset($branches[$storyModule->branch]))
{
$moduleTitle .= $branches[$storyModule->branch] . '/';
echo $branches[$storyModule->branch] . $lang->arrow;
}
foreach($modulePath as $key => $module)
{
$moduleTitle .= $module->name;
if(!common::printLink('projectstory', 'story', "projectID={$this->session->project}&productID=$story->product&branch=$story->branch&browseType=byModule&param=$module->id", $module->name, '', "data-app='project'")) echo $module->name;
if(isset($modulePath[$key + 1]))
{
$moduleTitle .= '/';
echo $lang->arrow;
}
}
}
$printModule = ob_get_contents();
ob_end_clean();
?>
<td title='<?php echo $moduleTitle?>'><?php echo $printModule?></td>
</tr>
<tr>
<th><?php echo $lang->story->status;?></th>
<td><span class='status-story status-<?php echo $story->status?>'><span class="label label-dot"></span> <?php echo $this->processStatus('story', $story);?></span></td>
</tr>
<tr>
<th><?php echo $lang->story->pri;?></th>
<td><span class='label-pri <?php echo 'label-pri-' . $story->pri;?>' title='<?php echo zget($lang->story->priList, $story->pri)?>'><?php echo zget($lang->story->priList, $story->pri)?></span></td>
</tr>
<tr>
<th><?php echo $lang->story->estimate;?></th>
<td title="<?php echo $story->estimate . ' ' . $lang->hourCommon;?>"><?php echo $story->estimate . $config->hourUnit;?></td>
</tr>
<tr>
<th><?php echo $lang->story->keywords;?></th>
<td><?php echo $story->keywords;?></td>
</tr>
<tr>
<th><?php echo $lang->story->legendMailto;?></th>
<td><?php $mailto = explode(',', $story->mailto); foreach($mailto as $account) {if(empty($account)) continue; echo "<span>" . zget($users, trim($account)) . '</span> &nbsp;'; }?></td>
</tr>
</tbody>
</table>
</div>
<div class='tab-pane' id='legendLifeTime'>
<table class="table table-data">
<tbody>
<tr>
<th class='thWidth'><?php echo $lang->story->openedBy;?></th>
<td><?php echo zget($users, $story->openedBy) . $lang->at . $story->openedDate;?></td>
</tr>
<tr>
<th><?php echo $lang->story->assignedTo;?></th>
<td><?php if($story->assignedTo) echo zget($users, $story->assignedTo) . $lang->at . $story->assignedDate;?></td>
</tr>
<?php if(!$checkSuperReviewed):?>
<tr>
<th><?php echo $lang->story->reviewers;?></th>
<td>
<?php
if($reviewers)
{
foreach($reviewers as $reviewer => $result)
{
echo !empty($result) ? '<span style="color: #cbd0db" title="' . $lang->story->reviewed . '"> ' . zget($users, $reviewer) . '</span>' : '<span title="' . $lang->story->toBeReviewed .'"> ' . zget($users, $reviewer) . '</span>';
}
}
?>
</td>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->story->reviewedDate;?></th>
<td><?php if($story->reviewedBy) echo $story->reviewedDate;?></td>
</tr>
<tr>
<th><?php echo $lang->story->closedBy;?></th>
<td><?php if($story->closedBy) echo zget($users, $story->closedBy) . $lang->at . $story->closedDate;?></td>
</tr>
<tr>
<th><?php echo $lang->story->closedReason;?></th>
<td>
<?php
if($story->closedReason) echo $lang->story->reasonList[$story->closedReason];
if(isset($story->extraStories[$story->duplicateStory]))
{
echo html::a(inlink('view', "storyID=$story->duplicateStory"), '#' . $story->duplicateStory . ' ' . $story->extraStories[$story->duplicateStory]);
}
?>
</td>
</tr>
<tr>
<th><?php echo $lang->story->lastEditedBy;?></th>
<td><?php if($story->lastEditedBy) echo zget($users, $story->lastEditedBy) . $lang->at . $story->lastEditedDate;?></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="cell">
<div class='tabs'>
<ul class='nav nav-tabs'>
<li class="active"><a href='#legendProjectAndTask' data-toggle='tab'><?php echo $lang->story->legendProjectAndTask;?></a></li>
</ul>
<div class='tab-content'>
<div class="tab-pane active" id='legendProjectAndTask'>
<ul class="list-unstyled">
<?php
foreach($story->tasks as $executionTasks)
{
foreach($executionTasks as $task)
{
if(!isset($executions[$task->execution])) continue;
$executionName = $executions[$task->execution];
$taskInfo = $task->id . '&nbsp<span class="label label-success label-outline">' . $this->lang->task->statusList[$task->status] . '</span>&nbsp' . $task->name;
$class = isonlybody() ? 'showinonlybody' : 'iframe';
echo "<li title='$task->name'>" . html::a($this->createLink('task', 'view', "taskID=$task->id", '', true), $taskInfo, '', "class=$class data-width='80%'");
echo html::a($this->createLink('execution', 'browse', "executionID=$task->execution"), $executionName, '', "class='text-muted'") . '</li>';
}
}
if(count($story->tasks) == 0)
{
foreach($story->executions as $executionID => $execution)
{
echo "<li title='$execution->name'>" . html::a($this->createLink('execution', 'browse', "executionID=$executionID"), $execution->name, '', "class='text-muted'") . '</li>';
}
}
?>
</ul>
</div>
</div>
</div>
</div>
<?php $this->printExtendFields($story, 'div', "position=right&inForm=0&inCell=1");?>
</div>
</div>
<?php if($this->app->getViewType() == 'xhtml'):?>
</div>
<?php endif;?>
<div id="mainActions" class='main-actions'>
<?php common::printPreAndNext($preAndNext);?>
</div>
<?php
js::set('canCreate', common::hasPriv('story', 'story'));
js::set('createStory', $lang->story->create);
js::set('productID', $story->product);
js::set('branch', $story->branch);
js::set('moduleID', $story->module);
js::set('storyType', $story->type);
js::set('unlink', $lang->story->unlink);
js::set('cancel', $lang->cancel);
js::set('rawModule', $this->app->rawModule);
?>
<script>
function handleLinkButtonClick()
{
var xxcUrl = "xxc:openInApp/zentao-integrated/" + encodeURIComponent(window.location.href.replace(/.display=card/, '').replace(/\.xhtml/, '.html'));
window.open(xxcUrl);
}
</script>
<?php include $this->app->getModuleRoot() . 'common/view/syntaxhighlighter.html.php';?>
<?php include $this->app->getModuleRoot() . 'common/view/footer.html.php';?>
+3
View File
@@ -0,0 +1,3 @@
<?php
$config->task->customBatchCreateFields .= ',lane,region';
$config->task->custom->batchCreateFields .= ',lane,region';
@@ -0,0 +1,47 @@
<?php
helper::importControl('task');
class myTask extends task
{
public function batchCreate($executionID = 0, $storyID = 0, $moduleID = 0, $taskID = 0, $iframe = 0, $extra = '')
{
$executions = $this->execution->getPairs();
if(empty($executions))
{
echo(js::alert($this->lang->task->kanbanDenied));
die(js::locate(helper::createLink('execution', 'create')));
}
$regionList = $this->loadModel('kanban')->getRegionPairs($executionID, 0, 'execution');
$this->view->regionList = $regionList;
$this->view->extra = $extra;
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
$lanes = array();
if(isset($output['laneID']))
{
$regionID = $this->dao->select("*")->from(TABLE_KANBANLANE)->where('id')->eq($output['laneID'])->fetch('region');
$lanes = $this->kanban->getLanePairsByRegion($regionID, 'task');
$this->view->regionID = $regionID;
}
$this->view->lanes = $lanes;
if(!empty($_POST))
{
$laneIDList = $_POST['lane'];
foreach($laneIDList as $key => $lane)
{
$_POST['column'][$key] = $this->dao->select("t1.id")->from(TABLE_KANBANCOLUMN)->alias('t1')
->leftJoin(TABLE_KANBANLANE)->alias('t2')
->on("t2.group = t1.group")
->where('t1.deleted')->eq('0')
->andWhere('t2.id')->eq($lane)
->andWhere('t1.type')->eq('wait')
->fetch('id');
}
}
return parent::batchCreate($executionID, $storyID, $moduleID, $taskID, $iframe, $extra);
}
}
@@ -0,0 +1,48 @@
<?php
helper::importControl('task');
class myTask extends task
{
public function create($executionID = 0, $storyID = 0, $moduleID = 0, $taskID = 0, $todoID = 0, $extra = '')
{
$executions = $this->execution->getPairs();
if(empty($executions))
{
echo(js::alert($this->lang->task->kanbanDenied));
die(js::locate(helper::createLink('execution', 'create')));
}
$regionList = $this->loadModel('kanban')->getRegionPairs($executionID, 0, 'execution');
$this->view->regionList = $regionList;
$this->view->laneList = array();
$this->view->extra = $extra;
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
$lanes = array();
if(isset($output['laneID']))
{
$regionID = $this->dao->select("*")->from(TABLE_KANBANLANE)->where('id')->eq($output['laneID'])->fetch('region');
$lanes = $this->kanban->getLanePairsByRegion($regionID, 'task');
$this->view->regionID = $regionID;
}
$this->view->lanes = $lanes;
if(isset($_POST['region']))
{
$regionID = $_POST['region'];
$laneID = $_POST['otherLane'];
$columnID = $this->dao->select("t1.id")->from(TABLE_KANBANCOLUMN)->alias('t1')
->leftJoin(TABLE_KANBANLANE)->alias('t2')
->on("t2.group = t1.group")
->where('t1.deleted')->eq('0')
->andWhere('t2.id')->eq($laneID)
->andWhere('t1.type')->eq('wait')
->fetch('id');
$extra = "laneID=$laneID,columnID=$columnID";
}
return parent::create($executionID, $storyID, $moduleID, $taskID, $todoID, $extra);
}
}
@@ -0,0 +1,79 @@
<?php
/**
* The task module zh-cn file of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package task
* @version $Id: zh-cn.php 5040 2013-07-06 06:22:18Z zhujinyonging@gmail.com $
* @link http://www.zentao.net
*/
$lang->task->index = "任务一览";
$lang->task->create = "建任务";
$lang->task->batchCreateChildren = "批量建子任务";
$lang->task->edit = "编辑任务";
$lang->task->deleteAction = "删除任务";
$lang->task->view = "查看任务";
$lang->task->startAction = "开始任务";
$lang->task->restartAction = "继续任务";
$lang->task->finishAction = "完成任务";
$lang->task->pauseAction = "暂停任务";
$lang->task->closeAction = "关闭任务";
$lang->task->cancelAction = "取消任务";
$lang->task->activateAction = "激活任务";
$lang->task->exportAction = "导出任务";
$lang->task->copy = '复制任务';
$lang->task->waitTask = '未开始的任务';
$lang->task->region = '所属区域';
$lang->task->lane = '所属泳道';
$lang->task->module = '所属目录';
$lang->task->common = '任务';
$lang->task->name = '任务名称';
$lang->task->type = '任务类型';
$lang->task->status = '任务状态';
$lang->task->desc = '任务描述';
$lang->task->assignAction = '指派任务';
$lang->task->multiple = '多人任务';
$lang->task->children = '子任务';
$lang->task->parent = '父任务';
/* Fields of zt_taskestimate. */
$lang->task->task = '任务';
$lang->task->dittoNotice = "该任务与上一任务不属于同一%s";
$lang->task->yesterdayFinished = '昨日完成任务数';
$lang->task->allTasks = '总任务';
$lang->task->afterChoices['continueAdding'] = "继续为该{$lang->SRCommon}添加任务";
$lang->task->afterChoices['toTaskList'] = '返回任务列表';
$lang->task->legendLife = '任务的一生';
$lang->task->legendDesc = '任务描述';
$lang->task->legendDetail = '任务详情';
$lang->task->confirmDelete = "您确定要删除这个任务吗?";
$lang->task->confirmDeleteEstimate = "您确定要删除这个记录吗?";
$lang->task->confirmFinish = '"预计剩余"为0,确认将任务状态改为"已完成"吗?';
$lang->task->confirmRecord = '"剩余"为0,任务将标记为"已完成",您确定吗?';
$lang->task->confirmTransfer = '"当前剩余"为0,任务将被转交,您确定吗?';
$lang->task->noTask = '暂时没有任务。';
$lang->task->kanbanDenied = '请先创建看板';
$lang->task->createDenied = '你不能在该项目添加任务';
$lang->task->cannotDeleteParent = '不能删除父任务。';
$lang->task->addChildTask = '因该任务已经产生消耗,为保证数据一致性,我们会帮您创建一条同名子任务记录该消耗。';
$lang->task->error->skipClose = '任务:%s 不是“已完成”或“已取消”状态,确定要关闭吗?';
$lang->task->error->consumed = '任务:%s工时不能小于0,忽略该任务工时的改动';
$lang->task->error->assignedTo = '当前状态的多人任务不能指派给任务团队外的成员。';
$lang->task->error->alreadyStarted = '此任务已被启动,不能重复启动!';
$lang->task->error->alreadyConsumed = '当前选中的父任务已有消耗。';
/* Report. */
$lang->task->report->value = '任务数';
$lang->task->report->charts['tasksPerExecution'] = '按' . $lang->executionCommon . '任务数统计';
$lang->task->report->charts['tasksPerModule'] = '按模块任务数统计';
$lang->task->report->charts['tasksPerType'] = '按任务类型统计';
$lang->task->report->charts['tasksPerStatus'] = '按任务状态统计';
@@ -0,0 +1,252 @@
<?php
/**
* The batch create view of task module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yangyang Shi <shiyangyang@cnezsoft.com>
* @package task
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include $this->app->getModuleRoot() . '/common/view/header.html.php';?>
<?php include $this->app->getModuleRoot() . '/common/view/datepicker.html.php';?>
<?php js::set('taskConsumed', $taskConsumed);?>
<?php js::set('addChildTask', $lang->task->addChildTask);?>
<style>.c-lane,.c-region{width:150px;}</style>
<div id="mainContent" class="main-content fade">
<div class="main-header clearfix">
<h2 class="pull-left">
<?php if($parent):?>
<span class='pull-left'><?php echo $parentTitle . $this->lang->colon;?></span>
<?php echo $lang->task->batchCreateChildren;?>
<?php else:?>
<?php echo $lang->task->batchCreate;?>
<?php endif;?>
</h2>
<?php if($execution->type != 'ops'):?>
<a class="checkbox-primary pull-left" id='zeroTaskStory' href='javascript:toggleZeroTaskStory();'>
<label><?php echo $lang->story->zeroTask;?></label>
</a>
<?php endif;?>
<div class="pull-right btn-toolbar">
<button type='button' data-toggle='modal' data-target="#importLinesModal" class="btn btn-primary"><?php echo $lang->pasteText;?></button>
<?php $customLink = $this->createLink('custom', 'ajaxSaveCustomFields', 'module=task&section=custom&key=batchCreateFields')?>
<?php include $this->app->getModuleRoot() . '/common/view/customfield.html.php';?>
</div>
</div>
<?php
$visibleFields = array();
$requiredFields = array();
foreach(explode(',', $showFields) as $field)
{
if($field)$visibleFields[$field] = '';
}
foreach(explode(',', $config->task->create->requiredFields) as $field)
{
if($field)
{
$requiredFields[$field] = '';
if(strpos(",{$config->task->customBatchCreateFields},", ",{$field},") !== false) $visibleFields[$field] = '';
}
}
$colspan = count($visibleFields) + 3;
?>
<form method='post' class='load-indicator batch-actions-form form-ajax' enctype='multipart/form-data' id="batchCreateForm">
<div class="table-responsive">
<table class="table table-form" id="tableBody">
<thead>
<tr>
<th class='c-id'><?php echo $lang->idAB;?></th>
<th class='c-module<?php echo zget($visibleFields, 'module', ' hidden') . zget($requiredFields, 'module', '', ' required');?>'><?php echo $lang->task->module?></th>
<?php if($execution->type != 'ops'):?>
<th class='c-story<?php echo zget($visibleFields, 'story', ' hidden') . zget($requiredFields, 'story', '', ' required');?>'><?php echo $lang->task->story;?></th>
<?php endif;?>
<th class='c-name required has-btn'><?php echo $lang->task->name;?></span></th>
<th class='c-region required<?php echo zget($visibleFields, 'region', ' hidden');?>'><?php echo $lang->task->region;?></th>
<th class='c-lane required<?php echo zget($visibleFields, 'lane', ' hidden');?>'><?php echo $lang->task->lane;?></th>
<th class='c-type required'><?php echo $lang->typeAB;?></span></th>
<th class='c-assigned<?php echo zget($visibleFields, 'assignedTo', ' hidden') . zget($requiredFields, 'assignedTo', '', ' required');?>'><?php echo $lang->task->assignedTo;?></th>
<th class='c-estimate<?php echo zget($visibleFields, 'estimate', ' hidden') . zget($requiredFields, 'estimate', '', ' required');?>'><?php echo $lang->task->estimateAB;?></th>
<th class='c-date<?php echo zget($visibleFields, 'estStarted', ' hidden') . zget($requiredFields, 'estStarted', '', ' required');?>'><?php echo $lang->task->estStarted;?></th>
<th class='c-date<?php echo zget($visibleFields, 'deadline', ' hidden') . zget($requiredFields, 'deadline', '', ' required');?>'><?php echo $lang->task->deadline;?></th>
<th class='c-desc<?php echo zget($visibleFields, 'desc', ' hidden') . zget($requiredFields, 'desc', '', ' required');?>'><?php echo $lang->task->desc;?></th>
<th class='c-pri<?php echo zget($visibleFields, 'pri', ' hidden') . zget($requiredFields, 'pri', '', ' required');?>'><?php echo $lang->task->pri;?></th>
<?php
$extendFields = $this->task->getFlowExtendFields();
foreach($extendFields as $extendField) echo "<th class='w-100px'>{$extendField->name}</th>";
?>
</tr>
</thead>
<tbody>
<?php
$stories['ditto'] = $lang->task->ditto;
$lang->task->typeList['ditto'] = $lang->task->ditto;
$members['ditto'] = $lang->task->ditto;
$modules['ditto'] = $lang->task->ditto;
if($execution->type == 'ops') $colspan = $colspan - 1;
?>
<?php for($i = 1; $i <= $config->task->batchCreate; $i++):?>
<?php
if($i == 1)
{
$currentStory = $storyID;
$type = '';
$member = '';
}
else
{
$currentStory = $type = $member = $moduleID = 'ditto';
}
?>
<?php $pri = 3;?>
<tr>
<td class='text-center'><?php echo $i;?></td>
<td <?php echo zget($visibleFields, 'module', "class='hidden'")?> style='overflow:visible'>
<?php echo html::select("module[$i]", $modules, $moduleID, "class='form-control chosen' onchange='setStories(this.value, $execution->id, $i)'")?>
<?php echo html::hidden("parent[$i]", $parent);?>
</td>
<?php if($execution->type != 'ops'):?>
<td <?php echo zget($visibleFields, 'story', "class='hidden'");?> style='overflow: visible'>
<div class='input-group'>
<?php echo html::select("story[$i]", $stories, $currentStory, "class='form-control chosen' onchange='setStoryRelated($i)'");?>
<span class='input-group-btn'>
<a id='preview<?php echo $i;?>' href='#' class='btn iframe btn-link btn-icon btn-copy' disabled='disabled' title='<?php echo $lang->preview; ?>'><i class='icon-search'></i></a>
<a href='javascript:copyStoryTitle(<?php echo $i;?>)' class='btn btn-link btn-icon btn-copy' title='<?php echo $lang->task->copyStoryTitle; ?>'><i class='icon-arrow-right'></i></a>
<?php echo html::hidden("storyEstimate$i") . html::hidden("storyDesc$i") . html::hidden("storyPri$i");?>
</span>
</div>
</td>
<?php endif;?>
<td style='overflow:visible'>
<div class="input-control has-icon-right">
<?php echo html::input("name[$i]", '', "class='form-control title-import'");?>
<div class="colorpicker">
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown"><span class="cp-title"></span><span class="color-bar"></span><i class="ic"></i></button>
<ul class="dropdown-menu clearfix pull-right">
<li class="heading"><?php echo $lang->task->colorTag;?><i class="icon icon-close"></i></li>
</ul>
<?php echo html::hidden("color[$i]", '', "data-provide='colorpicker' data-icon='color' data-wrapper='input-control-icon-right' data-update-color='#name\\[$i\\]'");?>
</div>
</div>
</td>
<td <?php echo zget($visibleFields, 'region', "class='hidden'")?> style='overflow:visible'><?php echo html::select("region[$i]", $regionList, isset($regionID) ? $regionID : '', "class='form-control chosen' onchange='loadLaneGroup(this.value, $i)'");?></td>
<td <?php echo zget($visibleFields, 'lane', "class='hidden'")?> style='overflow:visible'><?php echo html::select("lane[$i]", $lanes, '', "class='form-control chosen'");?></td>
<td><?php echo html::select("type[$i]", $lang->task->typeList, $type, 'class=form-control');?></td>
<td <?php echo zget($visibleFields, 'assignedTo', "class='hidden'")?> style='overflow:visible'><?php echo html::select("assignedTo[$i]", $members, $member, "class='form-control chosen'");?></td>
<td <?php echo zget($visibleFields, 'estimate', "class='hidden'")?>><?php echo html::input("estimate[$i]", '', "class='form-control text-center'");?></td>
<td <?php echo zget($visibleFields, 'estStarted', "class='hidden'")?>>
<div class='input-group'>
<?php
echo html::input("estStarted[$i]", '', "class='form-control text-center form-date' onkeyup='toggleCheck(this)'");
if($i != 0) echo "<span class='input-group-addon estStartedBox'><input type='checkbox' name='estStartedDitto[$i]' id='estStartedDitto$i' " . ($i> 0 ? "checked" : '') . " /> {$lang->task->ditto}</span>";
?>
</div>
</td>
<td <?php echo zget($visibleFields, 'deadline', "class='hidden'")?>>
<div class='input-group'>
<?php
echo html::input("deadline[$i]", '', "class='form-control text-center form-date' onkeyup='toggleCheck(this)'");
if($i != 0) echo "<span class='input-group-addon deadlineBox'><input type='checkbox' name='deadlineDitto[$i]' id='deadlineDitto$i' " . ($i> 0 ? "checked" : '') . " /> {$lang->task->ditto}</span>";
?>
</div>
</td>
<td <?php echo zget($visibleFields, 'desc', "class='hidden'")?>><?php echo html::textarea("desc[$i]", '', "rows='1' class='form-control autosize'");?></td>
<td <?php echo zget($visibleFields, 'pri', "class='hidden'")?>><?php echo html::select("pri[$i]", (array)$lang->task->priList, $pri, 'class=form-control');?></td>
<?php foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->loadModel('flow')->getFieldControl($extendField, '', $extendField->field . "[$i]") . "</td>";?>
</tr>
<?php endfor;?>
</tbody>
<tfoot>
<tr>
<td colspan='<?php echo $colspan?>' class='text-center form-actions'>
<?php echo html::submitButton();?>
<?php echo html::backButton();?>
</td>
</tr>
</tfoot>
</table>
</div>
</form>
</div>
<table class='template' id='trTemp'>
<tbody>
<tr>
<td class='text-center'>%s</td>
<td <?php echo zget($visibleFields, 'module', "class='hidden'")?> style='overflow:visible'>
<?php echo html::select("module[%s]", $modules, $moduleID, "class='form-control chosen' onchange='setStories(this.value, $execution->id, \"%s\")'")?>
<?php echo html::hidden("parent[%s]", $parent);?>
</td>
<td <?php echo zget($visibleFields, 'story', "class='hidden'");?> style='overflow: visible'>
<div class='input-group'>
<?php echo html::select("story[%s]", $stories, $currentStory, "class='form-control chosen' onchange='setStoryRelated(\"%s\")'");?>
<span class='input-group-btn'>
<a id="preview%s" href='#' class='btn iframe btn-link btn-icon btn-copy' disabled='disabled' title='<?php echo $lang->preview; ?>'><i class='icon-search'></i></a>
<a href='javascript:copyStoryTitle("%s")' class='btn btn-link btn-icon btn-copy' title='<?php echo $lang->task->copyStoryTitle; ?>'><i class='icon-arrow-right'></i></a>
</span>
</div>
</td>
<td style='overflow:visible'>
<div class="input-control has-icon-right">
<?php echo html::input("name[%s]", '', "class='form-control title-import'");?>
<div class="colorpicker">
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown"><span class="cp-title"></span><span class="color-bar"></span><i class="ic"></i></button>
<ul class="dropdown-menu clearfix pull-right">
<li class="heading"><?php echo $lang->task->colorTag;?><i class="icon icon-close"></i></li>
</ul>
<?php echo html::hidden("color[%s]", '', "data-provide='colorpicker-later' data-icon='color' data-wrapper='input-control-icon-right' data-update-color='#name\\[%s\\]'");?>
</div>
</div>
</div>
</td>
<td <?php echo zget($visibleFields, 'region', "class='hidden'")?> style='overflow:visible'><?php echo html::select("region[%s]", $regionList, isset($regionID) ? $regionID : '', "class='form-control chosen' onchange='loadLaneGroup(this.value, $i)'");?></td>
<td <?php echo zget($visibleFields, 'lane', "class='hidden'")?> style='overflow:visible'><?php echo html::select("lane[%s]", $lanes, '', "class='form-control chosen'");?></td>
<td><?php echo html::select("type[%s]", $lang->task->typeList, $type, 'class="form-control"');?></td>
<td <?php echo zget($visibleFields, 'assignedTo', "class='hidden'")?> style='overflow:visible'><?php echo html::select("assignedTo[%s]", $members, $member, "class='form-control chosen'");?></td>
<td <?php echo zget($visibleFields, 'estimate', "class='hidden'")?>><?php echo html::input("estimate[%s]", '', "class='form-control text-center'");?></td>
<td <?php echo zget($visibleFields, 'estStarted', "class='hidden'")?>>
<div class='input-group'>
<?php
echo html::input("estStarted[%s]", '', "class='form-control text-center form-date' onkeyup='toggleCheck(this)'");
echo "<span class='input-group-addon estStartedBox'><input type='checkbox' name='estStartedDitto[%s]' id='estStartedDitto%s' checked/>{$lang->task->ditto}</span>";
?>
</div>
</td>
<td <?php echo zget($visibleFields, 'deadline', "class='hidden'")?>>
<div class='input-group'>
<?php
echo html::input("deadline[%s]", '', "class='form-control text-center form-date' onkeyup='toggleCheck(this)'");
echo "<span class='input-group-addon deadlineBox'><input type='checkbox' name='deadlineDitto[%s]' id='deadlineDitto%s' checked/>{$lang->task->ditto}</span>";
?>
</div>
<td <?php echo zget($visibleFields, 'desc', "class='hidden'")?>><?php echo html::textarea("desc[%s]", '', "rows='1' class='form-control autosize'");?></td>
<td <?php echo zget($visibleFields, 'pri', "class='hidden'")?>><?php echo html::select("pri[%s]", (array)$lang->task->priList, $pri, 'class=form-control');?></td>
<?php foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->loadModel('flow')->getFieldControl($extendField, '', $extendField->field . "[%s]") . "</td>";?>
</tr>
</tbody>
</table>
<?php js::set('executionType', $execution->type);?>
<?php js::set('storyTasks', $storyTasks);?>
<?php js::set('mainField', 'name');?>
<?php js::set('ditto', $lang->task->ditto);?>
<?php js::set('storyID', $storyID);?>
<script>
function loadLaneGroup(regionID, num)
{
var link = createLink('kanban', 'ajaxGetLanes', 'regionID=' + regionID + '&type=task&field=lane&i=' + num);
$.post(link, function(data)
{
$('#lane' + num).replaceWith(data);
$('#lane' + num + '_chosen').remove();
$('#lane' + num).chosen();
})
console.log($('#lane' + num).val());
}
$(function()
{
$("select[id^='region']").change();
})
</script>
<?php include $this->app->getModuleRoot() . '/common/view/pastetext.html.php';?>
<?php include $this->app->getModuleRoot() . '/common/view/footer.html.php';?>
@@ -0,0 +1,6 @@
<script>
$(function()
{
for(var index = 1; index <= 10; index++) $('#batchCreateForm').append(`<input type="hidden" name="vision[${index}]" id="vision[${index}]" value="lite">`);
});
</script>
@@ -0,0 +1,354 @@
<?php
/**
* The create view of task module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package task
* @version $Id: create.html.php 5090 2013-07-10 05:49:24Z zhujinyonging@gmail.com $
* @link http://www.zentao.net
*/
?>
<?php include $this->app->getModuleRoot() . '/common/view/header.html.php';?>
<?php include $this->app->getModuleRoot() . '/common/view/kindeditor.html.php';?>
<?php include $this->app->getModuleRoot() . '/common/view/sortable.html.php';?>
<?php js::set('toTaskList', !empty($task->id));?>
<?php js::set('blockID', $blockID);?>
<?php if(!empty($storyID)):?>
<style> .title-group.required > .required:after {right: 110px;}</style>
<?php endif;?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->task->create;?></h2>
<div class='btn-toolbar pull-right'>
<?php $customLink = $this->createLink('custom', 'ajaxSaveCustomFields', 'module=task&section=custom&key=createFields')?>
<?php include $this->app->getModuleRoot() . '/common/view/customfield.html.php';?>
</div>
</div>
<?php
foreach(explode(',', $config->task->create->requiredFields) as $field)
{
if($field and strpos($showFields, $field) === false) $showFields .= ',' . $field;
}
?>
<form class='main-form form-ajax' method='post' enctype='multipart/form-data' id='dataform'>
<table class='table table-form'>
<?php if($execution->type != 'kanban' or $this->config->vision == 'lite'):?>
<tr>
<th><?php echo $lang->task->execution;?></th>
<td><?php echo html::select('execution', $executions, $execution->id, "class='form-control chosen' onchange='loadAll(this.value)' required");?></td><td></td><td></td>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->task->type;?></th>
<td><?php echo html::select('type', $lang->task->typeList, $task->type, "class='form-control chosen' onchange='setOwners(this.value)' required");?></td>
<td>
<div class="checkbox-primary hidden" id='selectTestStoryBox'>
<input type="checkbox" name='selectTestStory' id="selectTestStory" value='1' onchange='toggleSelectTestStory()' /><label for="selectTestStory" class="no-margin"><?php echo $lang->task->selectTestStory;?></label>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->task->module;?></th>
<td id='moduleIdBox'><?php echo html::select('module', $moduleOptionMenu, $task->module, "class='form-control chosen' onchange='setStories(this.value, $execution->id)'");?></td>
<td>
<div class="checkbox-primary">
<input type="checkbox" id="showAllModule" <?php if($showAllModule) echo 'checked';?>><label for="showAllModule" class="no-margin"><?php echo $lang->task->allModule;?></label>
</div>
</td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->task->assignedTo;?></th>
<td>
<div class="input-group" id="dataPlanGroup">
<?php echo html::select('assignedTo[]', $members, $task->assignedTo, "class='form-control chosen'");?>
<?php echo html::input('teamMember', '', "class='form-control team-group fix-border hidden' readonly='readonly'");?>
<span class="input-group-btn team-group hidden"><a class="btn br-0" href="#modalTeam" data-toggle="modal"><?php echo $lang->task->team;?></a></span>
</div>
</td>
<td>
<div class="checkbox-primary affair">
<input type="checkbox" name="multiple" value="1" id="multipleBox"><label for="multipleBox" class="no-margin"><?php echo $lang->task->multiple;?></label>
</div>
<button id='selectAllUser' type="button" class="btn btn-link<?php if($task->type !== 'affair') echo ' hidden';?>"><?php echo $lang->task->selectAllUser;?></button>
</td>
</tr>
<tr class='hide'>
<th><?php echo $lang->task->status;?></th>
<td><?php echo html::hidden('status', 'wait');?></td>
</tr>
<?php $this->printExtendFields('', 'table', 'columns=3');?>
<?php if(strpos(",$showFields,", ',story,') !== false and $execution->lifetime != 'ops'):?>
<tr>
<th><?php echo $lang->task->story;?></th>
<td colspan='3'>
<span id='storyBox' class="<?php if(!empty($stories)) echo 'hidden';?> "><?php printf($lang->task->noticeLinkStory, html::a($this->createLink('execution', 'linkStory', "executionID=$execution->id"), $lang->execution->linkStory, '_blank', 'class="text-primary"'), html::a("javascript:loadStories($execution->id)", $lang->refresh, '', 'class="text-primary"'));?></span>
<div class='input-group <?php if(empty($stories)) echo "hidden";?>'>
<?php echo html::select('story', array($task->story => empty($stories) ? '': $stories[$task->story]), $task->story, "class='form-control chosen' onchange='setStoryRelated();'");?>
<span class='input-group-btn' id='preview'><a href='#' class='btn iframe'><?php echo $lang->preview;?></a></span>
</div>
</td>
</tr>
<?php endif;?>
<?php if($execution->type != 'ops'):?>
<tr id='testStoryBox' class='hidden'>
<th><?php echo $lang->task->selectTestStory;?></th>
<td colspan='3'>
<table class='table table-form mg-0 table-bordered'>
<thead>
<tr>
<th class='w-150px'><?php echo $lang->task->storyAB;?></th>
<th class='w-80px'><?php echo $lang->task->pri;?></th>
<th class='w-300px'><?php echo $lang->task->datePlan;?></th>
<th class='w-150px'><?php echo $lang->task->assignedTo;?></th>
<th class='w-80px'><?php echo $lang->task->estimate;?></th>
<th class='w-80px'><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
<?php $i = 0;?>
<?php foreach($stories as $storyID => $storyTitle):?>
<?php if(empty($storyID) or isset($testStoryIdList[$storyID])) continue;?>
<tr>
<td><?php echo html::select("testStory[]", array($storyID => $storyTitle), $storyID, "class='form-control chosen'");?></td>
<td><?php echo html::select("testPri[]", $lang->task->priList, $task->pri, "class='form-control chosen'");?></td>
<td>
<div class='input-group'>
<?php echo html::input("testEstStarted[]", $task->estStarted, "class='form-control form-date' placeholder='{$lang->task->estStarted}'");?>
<span class='input-group-addon fix-border'>~</span>
<?php echo html::input("testDeadline[]", $task->deadline, "class='form-control form-date' placeholder='{$lang->task->deadline}'");?>
</div>
</td>
<td><?php echo html::select("testAssignedTo[]", $members, $task->assignedTo, "class='form-control chosen'");?></td>
<td><?php echo html::input("testEstimate[]", '', "class='form-control'");?></td>
<td class='text-center'>
<div class="btn-group">
<button type="button" class="btn btn-sm" tabindex="-1" onclick='addItem(this)'><i class="icon icon-plus"></i></button>
<button type="button" class="btn btn-sm" tabindex="-1" onclick='removeItem(this)'><i class="icon icon-close"></i></button>
</div>
</td>
</tr>
<?php $i++;?>
<?php if($i > 30) break;?>
<?php endforeach;?>
</tbody>
</table>
</td>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->task->name;?></th>
<td colspan='3'>
<div class="input-group title-group">
<div class="input-control has-icon-right">
<div class="colorpicker">
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown"><span class="cp-title"></span><span class="color-bar"></span><i class="ic"></i></button>
<ul class="dropdown-menu clearfix">
<li class="heading"><?php echo $lang->task->colorTag;?><i class="icon icon-close"></i></li>
</ul>
<input type="hidden" class="colorpicker" id="color" name="color" value="" data-icon="color" data-wrapper="input-control-icon-right" data-update-color="#name" data-provide="colorpicker">
</div>
<?php echo html::input('name', $task->name, "class='form-control' required");?>
<a href='javascript:copyStoryTitle();' id='copyButton' class='input-control-icon-right'><?php echo $lang->task->copyStoryTitle;?></a>
<?php echo html::hidden("storyEstimate") . html::hidden("storyDesc") . html::hidden("storyPri");?>
</div>
<?php if(strpos(",$showFields,", ',pri,') !== false): // begin print pri selector?>
<span class="input-group-addon fix-border br-0"><?php echo $lang->task->pri;?></span>
<?php
$hasCustomPri = false;
foreach($lang->task->priList as $priKey => $priValue)
{
if(!empty($priKey) and (string)$priKey != (string)$priValue)
{
$hasCustomPri = true;
break;
}
}
$priList = $lang->task->priList;
if(end($priList)) unset($priList[0]);
if(!isset($priList[$task->pri]))
{
reset($priList);
$task->pri = key($priList);
}
?>
<?php if($hasCustomPri):?>
<?php echo html::select('pri', (array)$priList, $task->pri, "class='form-control'");?>
<?php else: ?>
<div class="input-group-btn pri-selector" data-type="pri">
<button type="button" class="btn dropdown-toggle br-0" data-toggle="dropdown">
<span class="pri-text"><span class="label-pri label-pri-<?php echo empty($task->pri) ? '0' : $task->pri?>" title="<?php echo $task->pri?>"><?php echo $task->pri?></span></span> &nbsp;<span class="caret"></span>
</button>
<div class='dropdown-menu pull-right'>
<?php echo html::select('pri', (array)$priList, $task->pri, "class='form-control' data-provide='labelSelector' data-label-class='label-pri'");?>
</div>
</div>
<?php endif; ?>
<?php endif; // end print pri selector ?>
<?php if(strpos(",$showFields,", ',estimate,') !== false):?>
<div class='table-col w-120px'>
<div class="input-group">
<span class="input-group-addon fix-border br-0"><?php echo $lang->task->estimateAB;?></span>
<input type="text" name="estimate" id="estimate" value="<?php echo $task->estimate;?>" class="form-control" autocomplete="off">
</div>
</div>
<?php endif;?>
</div>
</td>
</tr>
<?php if(count($regionList) > 1 or count($lanes) > 1 or empty($extra)):?>
<tr>
<th><?php echo $lang->task->region;?></th>
<td><?php echo html::select('region', $regionList, isset($regionID) ? $regionID : '', "class='form-control chosen' onchange='loadLaneGroup(this.value)' required");?></td><td></td><td></td>
</tr>
<tr>
<th><?php echo $lang->task->lane;?></th>
<td><?php echo html::select('otherLane', $laneList, '', "class='form-control chosen' onchange='loadAll(this.value)' required");?></td><td></td><td></td>
</tr>
<tr>
<th><?php echo $lang->task->desc;?></th>
<td colspan='3'>
<?php echo $this->fetch('user', 'ajaxPrintTemplates', 'type=task&link=desc');?>
<?php echo html::textarea('desc', htmlSpecialString($task->desc), "rows='10' class='form-control'");?>
</td>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->files;?></th>
<td colspan='3'><?php echo $this->fetch('file', 'buildform');?></td>
</tr>
<?php
$hiddenEstStarted = strpos(",$showFields,", ',estStarted,') === false;
$hiddenDeadline = strpos(",$showFields,", ',deadline,') === false;
?>
<?php if(!$hiddenEstStarted or !$hiddenDeadline):?>
<tr>
<th><?php echo $lang->task->datePlan;?></th>
<td colspan='2'>
<div class='input-group'>
<?php if(!$hiddenEstStarted):?>
<?php echo html::input('estStarted', $task->estStarted, "class='form-control form-date' placeholder='{$lang->task->estStarted}'");?>
<?php endif;?>
<?php if(!$hiddenEstStarted and !$hiddenDeadline):?>
<span class='input-group-addon fix-border'>~</span>
<?php endif;?>
<?php if(!$hiddenDeadline):?>
<?php echo html::input('deadline', $task->deadline, "class='form-control form-date' placeholder='{$lang->task->deadline}'");?>
<?php endif;?>
</div>
</td>
</tr>
<?php endif;?>
<?php if(strpos(",$showFields,", ',mailto,') !== false):?>
<tr>
<th><?php echo $lang->story->mailto;?></th>
<td colspan='3'>
<div class="input-group">
<?php echo html::select('mailto[]', $execution->acl == 'private' ? $members : $users, str_replace(' ', '', $task->mailto), "class='form-control chosen' data-placeholder='{$lang->chooseUsersToMail}' multiple");?>
<?php if($execution->acl != 'private') echo $this->fetch('my', 'buildContactLists');?>
</div>
</td>
</tr>
<?php endif;?>
<?php if(!isonlybody()):?>
<tr id='after-tr'>
<th><?php echo $lang->task->afterSubmit;?></th>
<td colspan='3'><?php echo html::radio('after', $lang->task->afterChoices, !empty($task->id) ? 'toTaskList' : 'continueAdding');?></td>
</tr>
<?php endif;?>
<tr>
<td colspan='4' class='text-center form-actions'>
<?php echo html::submitButton();?>
<?php echo $gobackLink ? html::a($gobackLink, $lang->goback, '', 'class="btn btn-wide"') : html::backButton();?>
</td>
</tr>
</table>
<div class='modal fade modal-team' id='modalTeam' data-scroll-inside='false'>
<div class='modal-dialog'>
<div class='modal-content with-padding'>
<div class='modal-header'>
<button type='button' class='close' data-dismiss='modal'>
<i class="icon icon-close"></i>
</button>
<h4 class='modal-title'><?php echo $lang->task->team;?></h4>
</div>
<div class='modal-body'>
<table class="table table-form" id='taskTeamEditor'>
<tbody class='sortable'>
<tr class='template'>
<td><?php echo html::select("team[]", $members, '', "class='form-control chosen'");?></td>
<td>
<div class='input-group'>
<?php echo html::input("teamEstimate[]", '', "class='form-control text-center' placeholder='{$lang->task->estimateAB}'") ?>
<span class='input-group-addon'><?php echo $lang->task->hour;?></span>
</div>
</td>
<td class='w-130px sort-handler'>
<button type="button" class="btn btn-link btn-sm btn-icon btn-add"><i class="icon icon-plus"></i></button>
<button type='button' class='btn btn-link btn-sm btn-icon btn-move'><i class='icon-move'></i></button>
<button type="button" class="btn btn-link btn-sm btn-icon btn-delete"><i class="icon icon-close"></i></button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan='3' class='text-center'><?php echo html::a('javascript:void(0)', $lang->confirm, '', "class='btn btn-primary' data-dismiss='modal'");?></td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
<table class='hidden' id='testStoryTemplate'>
<tr>
<td><?php echo html::select("testStory[]", array(0 => ''), 0, "class='form-control chosen'");?></td>
<td><?php echo html::select("testPri[]", $lang->task->priList, '', "class='form-control chosen'");?></td>
<td>
<div class='input-group'>
<?php echo html::input("testEstStarted[]", '', "class='form-control form-date' placeholder='{$lang->task->estStarted}'");?>
<span class='input-group-addon fix-border'>~</span>
<?php echo html::input("testDeadline[]", '', "class='form-control form-date' placeholder='{$lang->task->deadline}'");?>
</div>
</td>
<td><?php echo html::select("testAssignedTo[]", array('' => ''), '', "class='form-control chosen'");?></td>
<td><?php echo html::input("testEstimate[]", '', "class='form-control'");?></td>
<td class='text-center'>
<div class="btn-group">
<button type="button" class="btn btn-sm" tabindex="-1" onclick='addItem(this)'><i class="icon icon-plus"></i></button>
<button type="button" class="btn btn-sm" tabindex="-1" onclick='removeItem(this)'><i class="icon icon-close"></i></button>
</div>
</td>
</tr>
</table>
<?php js::set('stories', $stories);?>
<?php js::set('storyPinYin', (empty($config->isINT) and class_exists('common')) ? common::convert2Pinyin($stories) : array());?>
<?php js::set('testStoryIdList', $testStoryIdList);?>
<?php js::set('executionID', $execution->id);?>
<script>
$(function()
{
var regionID = $('#region').val();
loadLaneGroup(regionID);
parent.$('body.hide-modal-close').removeClass('hide-modal-close');
})
function loadLaneGroup(regionID)
{
var link = createLink('kanban', 'ajaxGetLanes', 'regionID=' + regionID + '&type=task');
$.post(link, function(data)
{
$('#otherLane').replaceWith(data);
$('#otherLane_chosen').remove();
$('#otherLane').chosen();
})
}
</script>
<?php include $this->app->getModuleRoot() . '/common/view/footer.html.php';?>
@@ -0,0 +1,6 @@
<script>
$(function()
{
$('.main-form tr.hide > td').append('<input type="hidden" name="vision" id="vision" value="lite">');
});
</script>
@@ -0,0 +1,3 @@
<script>
$('#subHeader').remove();
</script>
@@ -0,0 +1,3 @@
<script>
$("a[href^='#legendMisc']").parent().remove();
</script>
@@ -0,0 +1,5 @@
<?php
$lang->todo->typeList['task'] = '任务';
unset($lang->todo->typeList['bug']);
unset($lang->todo->typeList['testtask']);
@@ -0,0 +1,8 @@
<?php $html = '<div class="divider"></div><button id="closeModal" type="button" class="btn btn-link" data-dismiss="modal"><i class="icon icon-close"></i></button>';?>
<script>
$(function()
{
for(var index = 0; index <= 9; index++) $('#todoBatchAddForm').append(`<input type="hidden" name="vision[${index}]" id="vision[${index}]" value="lite">`);
$('#mainContent .main-header .pull-right.btn-toolbar').append(<?php echo json_encode($html)?>);
});
</script>

Some files were not shown because too many files have changed in this diff Show More