diff --git a/.gitignore b/.gitignore
index 93a4a42186..47603db43b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/api/v1/entries/user.php b/api/v1/entries/user.php
index 0201193876..3db6a28954 100644
--- a/api/v1/entries/user.php
+++ b/api/v1/entries/user.php
@@ -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);
diff --git a/config/config.php b/config/config.php
index c4ffeac0f1..0af47c222b 100644
--- a/config/config.php
+++ b/config/config.php
@@ -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'; // 请求类型为GET:session变量名。 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);
+}
diff --git a/db/update16.4.sql b/db/update16.4.sql
index aecc125c66..dfd7d07147 100644
--- a/db/update16.4.sql
+++ b/db/update16.4.sql
@@ -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';
\ No newline at end of file
diff --git a/db/zentao.sql b/db/zentao.sql
index 7638baff66..8a91be5022 100644
--- a/db/zentao.sql
+++ b/db/zentao.sql
@@ -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'),
diff --git a/extension/custom/.gitkeep b/extension/custom/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/extension/lite/action/ext/lang/zh-cn/lite.php b/extension/lite/action/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..a2c6480f75
--- /dev/null
+++ b/extension/lite/action/ext/lang/zh-cn/lite.php
@@ -0,0 +1,89 @@
+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, 由 $actor 创建子目录 $extra。' . "\n";
+$lang->action->desc->linkchildstory = '$date, 由 $actor 关联子目录 $extra。' . "\n";
+$lang->action->desc->unlinkchildrenstory = '$date, 由 $actor 移除子目录 $extra。' . "\n";
+$lang->action->desc->linkparentstory = '$date, 由 $actor 关联到父目录 $extra。' . "\n";
+$lang->action->desc->unlinkparentstory = '$date, 由 $actor 从父目录$extra取消关联。' . "\n";
+$lang->action->desc->deletechildrenstory = '$date, 由 $actor 删除子目录$extra。' . "\n";
diff --git a/extension/lite/admin/ext/view/index.lite.html.hook.php b/extension/lite/admin/ext/view/index.lite.html.hook.php
new file mode 100644
index 0000000000..d9ce1f817c
--- /dev/null
+++ b/extension/lite/admin/ext/view/index.lite.html.hook.php
@@ -0,0 +1,3 @@
+
diff --git a/extension/lite/block/ext/config/lite.php b/extension/lite/block/ext/config/lite.php
new file mode 100644
index 0000000000..60ccd32b16
--- /dev/null
+++ b/extension/lite/block/ext/config/lite.php
@@ -0,0 +1,2 @@
+block->closed = '|html,|contribute';
diff --git a/extension/lite/block/ext/control/welcome.php b/extension/lite/block/ext/control/welcome.php
new file mode 100644
index 0000000000..22ce608d4f
--- /dev/null
+++ b/extension/lite/block/ext/control/welcome.php
@@ -0,0 +1,58 @@
+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();
+ }
+}
diff --git a/extension/lite/block/ext/lang/zh-cn/lite.php b/extension/lite/block/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..4d2c0d93f4
--- /dev/null
+++ b/extension/lite/block/ext/lang/zh-cn/lite.php
@@ -0,0 +1,50 @@
+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']);
diff --git a/extension/lite/block/ext/view/main.lite.html.hook.php b/extension/lite/block/ext/view/main.lite.html.hook.php
new file mode 100644
index 0000000000..e6cea48798
--- /dev/null
+++ b/extension/lite/block/ext/view/main.lite.html.hook.php
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/extension/lite/block/ext/view/printassigntomeblock.lite.html.hook.php b/extension/lite/block/ext/view/printassigntomeblock.lite.html.hook.php
new file mode 100644
index 0000000000..d0992c9834
--- /dev/null
+++ b/extension/lite/block/ext/view/printassigntomeblock.lite.html.hook.php
@@ -0,0 +1,3 @@
+
diff --git a/extension/lite/block/ext/view/welcome.html.php b/extension/lite/block/ext/view/welcome.html.php
new file mode 100644
index 0000000000..5ae959a074
--- /dev/null
+++ b/extension/lite/block/ext/view/welcome.html.php
@@ -0,0 +1,46 @@
+
+ * @package block
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+
+
+
+
+
block->leftToday?>
+
+
+
block->undone?>
+
createLink('my', 'work', 'mode=task'), (int)$data['undone']);?>
+
+
+
block->delaying?>
+
createLink('my', 'work', 'mode=task'), (int)$data['delaying']);?>
+
+
+
block->delayed?>
+
createLink('my', 'work', 'mode=task'), (int)$data['delayed']);?>
+
+
+
+
+
diff --git a/extension/lite/common/ext/lang/zh-cn/lite.php b/extension/lite/common/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..029f37b3c1
--- /dev/null
+++ b/extension/lite/common/ext/lang/zh-cn/lite.php
@@ -0,0 +1,257 @@
+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'] = "";
+ $lang->navIcons['oa'] = "";
+ $lang->navIcons['workflow'] = "";
+
+ $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';
diff --git a/extension/lite/common/ext/view/footer.lite.html.hook.php b/extension/lite/common/ext/view/footer.lite.html.hook.php
new file mode 100644
index 0000000000..e0c71cde0c
--- /dev/null
+++ b/extension/lite/common/ext/view/footer.lite.html.hook.php
@@ -0,0 +1,4 @@
+
diff --git a/extension/lite/company/ext/lang/zh-cn/lite.php b/extension/lite/company/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..f09b1918cf
--- /dev/null
+++ b/extension/lite/company/ext/lang/zh-cn/lite.php
@@ -0,0 +1,3 @@
+company->execution = '看板';
+$lang->company->product = '项目';
diff --git a/extension/lite/custom/ext/config/lite.php b/extension/lite/custom/ext/config/lite.php
new file mode 100644
index 0000000000..6ca05649d1
--- /dev/null
+++ b/extension/lite/custom/ext/config/lite.php
@@ -0,0 +1,12 @@
+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';
diff --git a/extension/lite/custom/ext/lang/zh-cn/lite.php b/extension/lite/custom/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..9d1feed8cd
--- /dev/null
+++ b/extension/lite/custom/ext/lang/zh-cn/lite.php
@@ -0,0 +1,28 @@
+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');
diff --git a/extension/lite/datatable/ext/model/lite.php b/extension/lite/datatable/ext/model/lite.php
new file mode 100644
index 0000000000..2e8b415aed
--- /dev/null
+++ b/extension/lite/datatable/ext/model/lite.php
@@ -0,0 +1,36 @@
+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;
+}
diff --git a/extension/lite/dev/ext/config/lite.php b/extension/lite/dev/ext/config/lite.php
new file mode 100644
index 0000000000..e9d67acefe
--- /dev/null
+++ b/extension/lite/dev/ext/config/lite.php
@@ -0,0 +1,63 @@
+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';
diff --git a/extension/lite/dev/ext/lang/zh-cn/lite.php b/extension/lite/dev/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..9ef59bcb45
--- /dev/null
+++ b/extension/lite/dev/ext/lang/zh-cn/lite.php
@@ -0,0 +1,87 @@
+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'] = '其他';
diff --git a/extension/lite/doc/ext/lang/zh-cn/lite.php b/extension/lite/doc/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..f6d01c3474
--- /dev/null
+++ b/extension/lite/doc/ext/lang/zh-cn/lite.php
@@ -0,0 +1,4 @@
+doc->libTypeList = array();
+$lang->doc->libTypeList['project'] = '项目文档库';
+$lang->doc->libTypeList['custom'] = '自定义文档库';
diff --git a/extension/lite/doc/ext/model/lite.php b/extension/lite/doc/ext/model/lite.php
new file mode 100644
index 0000000000..c40f08af92
--- /dev/null
+++ b/extension/lite/doc/ext/model/lite.php
@@ -0,0 +1,13 @@
+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;
+}
diff --git a/extension/lite/doc/ext/view/create.lite.html.hook.php b/extension/lite/doc/ext/view/create.lite.html.hook.php
new file mode 100644
index 0000000000..b589a10995
--- /dev/null
+++ b/extension/lite/doc/ext/view/create.lite.html.hook.php
@@ -0,0 +1,6 @@
+
diff --git a/extension/lite/doc/ext/view/createlib.lite.html.hook.php b/extension/lite/doc/ext/view/createlib.lite.html.hook.php
new file mode 100644
index 0000000000..b589a10995
--- /dev/null
+++ b/extension/lite/doc/ext/view/createlib.lite.html.hook.php
@@ -0,0 +1,6 @@
+
diff --git a/extension/lite/doc/ext/view/objectlibs.lite.html.hook.php b/extension/lite/doc/ext/view/objectlibs.lite.html.hook.php
new file mode 100644
index 0000000000..1ac68e29da
--- /dev/null
+++ b/extension/lite/doc/ext/view/objectlibs.lite.html.hook.php
@@ -0,0 +1,53 @@
+app->tab == 'project'):?>
+
+
+app->tab == 'doc'):?>
+
+
+
+deleted and $doc->version > 1 and common::hasPriv('doc', 'diff')):?>
+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 = "";
+$diffHtml .= "";
+$diffHtml .= "";
+$diffHtml .= "
";
+?>
+
+
diff --git a/extension/lite/doc/ext/view/tablecontents.lite.html.hook.php b/extension/lite/doc/ext/view/tablecontents.lite.html.hook.php
new file mode 100644
index 0000000000..9259a1a1fd
--- /dev/null
+++ b/extension/lite/doc/ext/view/tablecontents.lite.html.hook.php
@@ -0,0 +1 @@
+
diff --git a/extension/lite/effort/ext/view/calendar.html.php b/extension/lite/effort/ext/view/calendar.html.php
new file mode 100644
index 0000000000..cbe294010a
--- /dev/null
+++ b/extension/lite/effort/ext/view/calendar.html.php
@@ -0,0 +1,210 @@
+
+ * @package calendar
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+getModuleRoot() . 'common/view/datepicker.html.php';?>
+getExtensionRoot() . 'biz/common/ext/view/calendar.html.php';?>
+
+
+ todo->all . " {$todoCount}", '', "class='btn btn-link'");?>
+
+ effort->all . " {$effortCount}", '', "class='btn btn-link'");?>
+
+
+
+ id}&orderBy=date_asc&date=_date_") . '")', " " . $lang->effort->export, '', "class='btn btn-link'") ?>
+ " . $lang->effort->create, '', "class='btn btn-primary' id='batchCreate'", '', true);
+ ?>
+
+
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/execution/ext/control/kanban.php b/extension/lite/execution/ext/control/kanban.php
new file mode 100644
index 0000000000..69571b03f5
--- /dev/null
+++ b/extension/lite/execution/ext/control/kanban.php
@@ -0,0 +1,76 @@
+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 .= "";
+ $TRActions .= html::a('javascript:;', $this->lang->execution->kanbanGroup[$groupBy] . "", '', "data-toggle='dropdown' data- class='btn btn-link'");
+ $TRActions .= "
";
+ $TRActions .= html::a('javascript:fullScreen()', " " . $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 .= "";
+ $TRActions .= html::a('javascript:;', "" . $this->lang->kanban->setting, '', "data-toggle='dropdown' data- class='btn btn-link'");
+ $TRActions .= "
";
+ }
+
+ $canCreateTask = common::hasPriv('task', 'create');
+ $canBatchCreateTask = common::hasPriv('task', 'batchCreate');
+ if($canCreateTask or $canBatchCreateTask)
+ {
+ $TRActions .= "";
+ $TRActions .= "";
+ $TRActions .= "
";
+ }
+ $this->lang->TRActions = $TRActions;
+
+ $browseType = 'task';
+ parent::kanban($executionID, $browseType, $orderBy, $groupBy);
+ }
+}
diff --git a/extension/lite/execution/ext/lang/zh-cn/lite.php b/extension/lite/execution/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..7999584f13
--- /dev/null
+++ b/extension/lite/execution/ext/lang/zh-cn/lite.php
@@ -0,0 +1,24 @@
+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'] = "私有(团队成员和项目负责人可访问)";
diff --git a/extension/lite/execution/ext/model/lite.php b/extension/lite/execution/ext/model/lite.php
new file mode 100644
index 0000000000..e3c74aa12f
--- /dev/null
+++ b/extension/lite/execution/ext/model/lite.php
@@ -0,0 +1,107 @@
+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 .= "";
+ $modulePageNav .= "";
+ $modulePageNav .= "
";
+
+ 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 .= "";
+ $TRActions .= html::a('javascript:;', " " . $subMenu->$currentMethod['name'] . "", '', "data-toggle='dropdown' class='btn btn-link'");
+ $TRActions .= "
";
+ return $TRActions;
+}
diff --git a/extension/lite/execution/ext/view/create.html.php b/extension/lite/execution/ext/view/create.html.php
new file mode 100644
index 0000000000..9aa6408671
--- /dev/null
+++ b/extension/lite/execution/ext/view/create.html.php
@@ -0,0 +1,115 @@
+
+ * @package execution
+ * @version $Id: create.html.php 4728 2013-05-03 06:14:34Z chencongzhi520@gmail.com $
+ * @link http://www.zentao.net
+ */
+?>
+
+createLink('execution', 'kanban', 'executionID=' . $executionID);?>
+
+
+
+getModuleRoot() . 'common/view/header.html.php';?>
+getModuleRoot() . 'common/view/kindeditor.html.php';?>
+app->getClientLang() . '/lite.php';?>
+
+execution->weekend);?>
+execution->placeholder);?>
+execution->errorSameProducts);?>
+execution->errorSameBranches);?>
+
+
+
+systemMode);?>
+project->common);?>
+
+systemMode);?>
+
+
+
+
execution->create;?>
+
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/execution/ext/view/edit.lite.html.hook.php b/extension/lite/execution/ext/view/edit.lite.html.hook.php
new file mode 100644
index 0000000000..2a25dbf3d5
--- /dev/null
+++ b/extension/lite/execution/ext/view/edit.lite.html.hook.php
@@ -0,0 +1,10 @@
+
diff --git a/extension/lite/execution/ext/view/kanban.lite.html.hook.php b/extension/lite/execution/ext/view/kanban.lite.html.hook.php
new file mode 100644
index 0000000000..8d5ff1682c
--- /dev/null
+++ b/extension/lite/execution/ext/view/kanban.lite.html.hook.php
@@ -0,0 +1,10 @@
+
+
diff --git a/extension/lite/execution/ext/view/task.lite.html.hook.php b/extension/lite/execution/ext/view/task.lite.html.hook.php
new file mode 100644
index 0000000000..f0295754dd
--- /dev/null
+++ b/extension/lite/execution/ext/view/task.lite.html.hook.php
@@ -0,0 +1,3 @@
+
diff --git a/extension/lite/flow/ext/view/browse.flow.html.hook.php b/extension/lite/flow/ext/view/browse.flow.html.hook.php
new file mode 100644
index 0000000000..c66dc67377
--- /dev/null
+++ b/extension/lite/flow/ext/view/browse.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/flow/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/flow/ext/view/create.flow.html.hook.php b/extension/lite/flow/ext/view/create.flow.html.hook.php
new file mode 100644
index 0000000000..c66dc67377
--- /dev/null
+++ b/extension/lite/flow/ext/view/create.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/flow/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/group/ext/lang/en/lite.php b/extension/lite/group/ext/lang/en/lite.php
new file mode 100644
index 0000000000..71b1dad82e
--- /dev/null
+++ b/extension/lite/group/ext/lang/en/lite.php
@@ -0,0 +1,2 @@
+moduleOrder = array();
+
+$lang->moduleOrder[0] = 'index';
+$lang->moduleOrder[5] = 'my';
+$lang->moduleOrder[10] = 'todo';
+
+$lang->moduleOrder[20] = 'personnel';
+$lang->moduleOrder[30] = 'story';
+
+$lang->moduleOrder[45] = 'project';
+$lang->moduleOrder[50] = 'projectstory';
+$lang->moduleOrder[55] = 'execution';
+$lang->moduleOrder[60] = 'task';
+
+$lang->moduleOrder[110] = 'doc';
+
+$lang->moduleOrder[120] = 'company';
+$lang->moduleOrder[125] = 'dept';
+$lang->moduleOrder[130] = 'group';
+$lang->moduleOrder[135] = 'user';
+
+$lang->moduleOrder[140] = 'admin';
+$lang->moduleOrder[142] = 'stage';
+$lang->moduleOrder[145] = 'extension';
+$lang->moduleOrder[150] = 'custom';
+$lang->moduleOrder[155] = 'action';
+
+$lang->moduleOrder[175] = 'search';
+$lang->moduleOrder[180] = 'tree';
+$lang->moduleOrder[190] = 'file';
+$lang->moduleOrder[195] = 'misc';
+$lang->moduleOrder[200] = 'backup';
+$lang->moduleOrder[205] = 'cron';
+$lang->moduleOrder[215] = 'message';
+
+$lang->resource = new stdclass();
+
+/* Index module. */
+$lang->resource->index = new stdclass();
+$lang->resource->index->index = 'index';
+
+$lang->index->methodOrder[0] = 'index';
+
+/* My module. */
+$lang->resource->my = new stdclass();
+$lang->resource->my->index = 'indexAction';
+$lang->resource->my->todo = 'todo';
+$lang->resource->my->calendar = 'calendarAction';
+$lang->resource->my->work = 'workAction';
+$lang->resource->my->contribute = 'contributeAction';
+$lang->resource->my->profile = 'profileAction';
+$lang->resource->my->uploadAvatar = 'uploadAvatar';
+$lang->resource->my->preference = 'preference';
+$lang->resource->my->dynamic = 'dynamicAction';
+$lang->resource->my->editProfile = 'editProfile';
+$lang->resource->my->changePassword = 'changePassword';
+$lang->resource->my->manageContacts = 'manageContacts';
+$lang->resource->my->deleteContacts = 'deleteContacts';
+$lang->resource->my->score = 'score';
+$lang->resource->my->team = 'team';
+$lang->resource->my->requirement = 'requirement';
+$lang->resource->my->story = 'story';
+$lang->resource->my->task = 'task';
+$lang->resource->my->bug = 'bug';
+$lang->resource->my->doc = 'doc';
+$lang->resource->my->testtask = 'testtask';
+$lang->resource->my->testcase = 'testcase';
+$lang->resource->my->execution = 'execution';
+
+$lang->my->methodOrder[1] = 'index';
+$lang->my->methodOrder[5] = 'todo';
+$lang->my->methodOrder[10] = 'work';
+$lang->my->methodOrder[15] = 'contribute';
+$lang->my->methodOrder[20] = 'project';
+$lang->my->methodOrder[25] = 'profile';
+$lang->my->methodOrder[30] = 'uploadAvatar';
+$lang->my->methodOrder[35] = 'preference';
+$lang->my->methodOrder[40] = 'dynamic';
+$lang->my->methodOrder[45] = 'editProfile';
+$lang->my->methodOrder[50] = 'changePassword';
+$lang->my->methodOrder[55] = 'manageContacts';
+$lang->my->methodOrder[60] = 'deleteContacts';
+$lang->my->methodOrder[65] = 'score';
+$lang->my->methodOrder[70] = 'unbind';
+$lang->my->methodOrder[75] = 'team';
+$lang->my->methodOrder[80] = 'requirement';
+$lang->my->methodOrder[85] = 'story';
+$lang->my->methodOrder[90] = 'task';
+$lang->my->methodOrder[95] = 'bug';
+$lang->my->methodOrder[100] = 'testtask';
+$lang->my->methodOrder[105] = 'testcase';
+$lang->my->methodOrder[110] = 'execution';
+$lang->my->methodOrder[115] = 'doc';
+
+/* Todo. */
+$lang->resource->todo = new stdclass();
+$lang->resource->todo->create = 'create';
+$lang->resource->todo->createcycle = 'createCycle';
+$lang->resource->todo->batchCreate = 'batchCreate';
+$lang->resource->todo->edit = 'edit';
+$lang->resource->todo->batchEdit = 'batchEdit';
+$lang->resource->todo->view = 'view';
+$lang->resource->todo->delete = 'delete';
+$lang->resource->todo->export = 'export';
+$lang->resource->todo->start = 'start';
+$lang->resource->todo->finish = 'finish';
+$lang->resource->todo->batchFinish = 'batchFinish';
+$lang->resource->todo->import2Today = 'import2Today';
+$lang->resource->todo->assignTo = 'assignAction';
+$lang->resource->todo->activate = 'activate';
+$lang->resource->todo->close = 'close';
+$lang->resource->todo->batchClose = 'batchClose';
+
+/* Personnel . */
+$lang->resource->personnel = new stdclass();
+$lang->resource->personnel->accessible = 'accessible';
+$lang->resource->personnel->invest = 'invest';
+$lang->resource->personnel->whitelist = 'whitelist';
+$lang->resource->personnel->addWhitelist = 'addWhitelist';
+$lang->resource->personnel->unbindWhitelist = 'unbindWhitelist';
+
+$lang->personnel->methodOrder[5] = 'accessible';
+$lang->personnel->methodOrder[10] = 'invest';
+$lang->personnel->methodOrder[15] = 'whitelist';
+$lang->personnel->methodOrder[20] = 'addWhitelist';
+$lang->personnel->methodOrder[25] = 'unbindWhitelist';
+
+global $config;
+if($config->systemMode == 'new')
+{
+ $lang->resource->my->project = 'project';
+
+ /* Project. */
+ $lang->resource->project = new stdclass();
+ $lang->resource->project->index = 'index';
+ $lang->resource->project->browse = 'browse';
+ $lang->resource->project->kanban = 'kanban';
+ $lang->resource->project->programTitle = 'moduleOpen';
+ $lang->resource->project->create = 'create';
+ $lang->resource->project->edit = 'edit';
+ $lang->resource->project->batchEdit = 'batchEdit';
+ $lang->resource->project->group = 'group';
+ $lang->resource->project->createGroup = 'createGroup';
+ $lang->resource->project->managePriv = 'managePriv';
+ $lang->resource->project->manageMembers = 'manageMembers';
+ $lang->resource->project->manageGroupMember = 'manageGroupMember';
+ $lang->resource->project->copyGroup = 'copyGroup';
+ $lang->resource->project->editGroup = 'editGroup';
+ $lang->resource->project->start = 'start';
+ $lang->resource->project->suspend = 'suspend';
+ $lang->resource->project->close = 'close';
+ $lang->resource->project->activate = 'activate';
+ $lang->resource->project->delete = 'delete';
+ $lang->resource->project->view = 'view';
+ $lang->resource->project->whitelist = 'whitelist';
+ $lang->resource->project->addWhitelist = 'addWhitelist';
+ $lang->resource->project->unbindWhitelist = 'unbindWhitelist';
+ $lang->resource->project->manageProducts = 'manageProducts';
+ $lang->resource->project->dynamic = 'dynamic';
+ $lang->resource->project->qa = 'qa';
+ $lang->resource->project->bug = 'bug';
+ $lang->resource->project->testcase = 'testcase';
+ $lang->resource->project->testtask = 'testtask';
+ $lang->resource->project->testreport = 'testreport';
+ $lang->resource->project->execution = 'execution';
+ $lang->resource->project->export = 'export';
+ $lang->resource->project->createGuide = 'createGuide';
+ $lang->resource->project->updateOrder = 'updateOrder';
+ $lang->resource->project->team = 'teamAction';
+ $lang->resource->project->unlinkMember = 'unlinkMember';
+
+ $lang->project->methodOrder[0] = 'index';
+ $lang->project->methodOrder[5] = 'browse';
+ $lang->project->methodOrder[10] = 'kanban';
+ $lang->project->methodOrder[15] = 'projectTitle';
+ $lang->project->methodOrder[20] = 'create';
+ $lang->project->methodOrder[25] = 'edit';
+ $lang->project->methodOrder[30] = 'batchEdit';
+ $lang->project->methodOrder[35] = 'group';
+ $lang->project->methodOrder[40] = 'createGroup';
+ $lang->project->methodOrder[45] = 'managePriv';
+ $lang->project->methodOrder[50] = 'manageMembers';
+ $lang->project->methodOrder[55] = 'manageGroupMember';
+ $lang->project->methodOrder[60] = 'copyGroup';
+ $lang->project->methodOrder[65] = 'editGroup';
+ $lang->project->methodOrder[70] = 'start';
+ $lang->project->methodOrder[75] = 'suspend';
+ $lang->project->methodOrder[80] = 'close';
+ $lang->project->methodOrder[85] = 'activate';
+ $lang->project->methodOrder[90] = 'updateOrder';
+ $lang->project->methodOrder[95] = 'delete';
+ $lang->project->methodOrder[100] = 'view';
+ $lang->project->methodOrder[105] = 'whitelist';
+ $lang->project->methodOrder[110] = 'addWhitelist';
+ $lang->project->methodOrder[115] = 'unbindWhitelist';
+ $lang->project->methodOrder[120] = 'manageProducts';
+ $lang->project->methodOrder[125] = 'view';
+ $lang->project->methodOrder[130] = 'dynamic';
+ $lang->project->methodOrder[140] = 'qa';
+ $lang->project->methodOrder[145] = 'bug';
+ $lang->project->methodOrder[150] = 'testcase';
+ $lang->project->methodOrder[155] = 'testtask';
+ $lang->project->methodOrder[160] = 'testreport';
+ $lang->project->methodOrder[165] = 'execution';
+ $lang->project->methodOrder[170] = 'export';
+ $lang->project->methodOrder[175] = 'createGuide';
+ $lang->project->methodOrder[180] = 'updateOrder';
+ $lang->project->methodOrder[185] = 'team';
+ $lang->project->methodOrder[190] = 'unlinkMember';
+
+ /* Project Story. */
+ $lang->resource->projectstory = new stdclass();
+ $lang->resource->projectstory->story = 'story';
+ $lang->resource->projectstory->track = 'trackAction';
+ $lang->resource->projectstory->view = 'view';
+ $lang->resource->projectstory->linkStory = 'linkStory';
+ $lang->resource->projectstory->unlinkStory = 'unlinkStory';
+ $lang->resource->projectstory->batchUnlinkStory = 'batchUnlinkStory';
+ $lang->resource->projectstory->importplanstories = 'importplanstories';
+
+ $lang->projectstory->methodOrder[5] = 'story';
+ $lang->projectstory->methodOrder[10] = 'track';
+ $lang->projectstory->methodOrder[15] = 'view';
+ $lang->projectstory->methodOrder[20] = 'linkStory';
+ $lang->projectstory->methodOrder[25] = 'unlinkStory';
+ $lang->projectstory->methodOrder[23] = 'importplanstories';
+}
+
+/* Story. */
+$lang->resource->story = new stdclass();
+$lang->resource->story->create = 'create';
+$lang->resource->story->batchCreate = 'batchCreate';
+$lang->resource->story->edit = 'editAction';
+$lang->resource->story->linkStory = 'linkStory';
+$lang->resource->story->batchEdit = 'batchEdit';
+$lang->resource->story->export = 'exportAction';
+$lang->resource->story->delete = 'deleteAction';
+$lang->resource->story->view = 'view';
+$lang->resource->story->change = 'changeAction';
+$lang->resource->story->review = 'reviewAction';
+$lang->resource->story->batchReview = 'batchReview';
+$lang->resource->story->recall = 'recall';
+$lang->resource->story->assignTo = 'assignAction';
+$lang->resource->story->close = 'closeAction';
+$lang->resource->story->batchClose = 'batchClose';
+$lang->resource->story->activate = 'activateAction';
+$lang->resource->story->tasks = 'tasks';
+$lang->resource->story->bugs = 'bugs';
+$lang->resource->story->cases = 'cases';
+$lang->resource->story->zeroCase = 'zeroCase';
+$lang->resource->story->report = 'reportAction';
+$lang->resource->story->batchChangePlan = 'batchChangePlan';
+$lang->resource->story->batchChangeBranch = 'batchChangeBranch';
+$lang->resource->story->batchChangeStage = 'batchChangeStage';
+$lang->resource->story->batchAssignTo = 'batchAssignTo';
+$lang->resource->story->batchChangeModule = 'batchChangeModule';
+$lang->resource->story->batchToTask = 'batchToTask';
+$lang->resource->story->track = 'trackAB';
+$lang->resource->story->processStoryChange = 'processStoryChange';
+
+$lang->story->methodOrder[5] = 'create';
+$lang->story->methodOrder[10] = 'batchCreate';
+$lang->story->methodOrder[15] = 'edit';
+$lang->story->methodOrder[20] = 'export';
+$lang->story->methodOrder[25] = 'delete';
+$lang->story->methodOrder[30] = 'view';
+$lang->story->methodOrder[35] = 'change';
+$lang->story->methodOrder[40] = 'review';
+$lang->story->methodOrder[45] = 'batchReview';
+$lang->story->methodOrder[50] = 'recall';
+$lang->story->methodOrder[55] = 'close';
+$lang->story->methodOrder[60] = 'batchClose';
+$lang->story->methodOrder[65] = 'batchChangePlan';
+$lang->story->methodOrder[70] = 'batchChangeStage';
+$lang->story->methodOrder[75] = 'assignTo';
+$lang->story->methodOrder[80] = 'batchAssignTo';
+$lang->story->methodOrder[85] = 'activate';
+$lang->story->methodOrder[90] = 'tasks';
+$lang->story->methodOrder[95] = 'bugs';
+$lang->story->methodOrder[100] = 'cases';
+$lang->story->methodOrder[105] = 'zeroCase';
+$lang->story->methodOrder[110] = 'report';
+$lang->story->methodOrder[115] = 'linkStory';
+$lang->story->methodOrder[120] = 'batchChangeBranch';
+$lang->story->methodOrder[125] = 'batchChangeModule';
+$lang->story->methodOrder[130] = 'batchToTask';
+$lang->story->methodOrder[135] = 'track';
+$lang->story->methodOrder[140] = 'processStoryChange';
+
+/* Kanban */
+$lang->resource->kanban = new stdclass();
+$lang->resource->kanban->space = 'spaceCommon';
+$lang->resource->kanban->createSpace = 'createSpace';
+$lang->resource->kanban->editSpace = 'editSpace';
+$lang->resource->kanban->closeSpace = 'closeSpace';
+$lang->resource->kanban->deleteSpace = 'deleteSpace';
+$lang->resource->kanban->sortSpace = 'sortSpace';
+$lang->resource->kanban->create = 'create';
+$lang->resource->kanban->edit = 'edit';
+$lang->resource->kanban->view = 'view';
+$lang->resource->kanban->close = 'close';
+$lang->resource->kanban->delete = 'delete';
+$lang->resource->kanban->createRegion = 'createRegion';
+$lang->resource->kanban->editRegion = 'editRegion';
+$lang->resource->kanban->sortRegion = 'sortRegion';
+$lang->resource->kanban->sortGroup = 'sortGroup';
+$lang->resource->kanban->deleteRegion = 'deleteRegion';
+$lang->resource->kanban->createLane = 'createLane';
+$lang->resource->kanban->setLane = 'setLane';
+$lang->resource->kanban->sortLane = 'sortLane';
+$lang->resource->kanban->deleteLane = 'deleteLane';
+$lang->resource->kanban->createColumn = 'createColumn';
+$lang->resource->kanban->splitColumn = 'splitColumn';
+$lang->resource->kanban->archiveColumn = 'archiveColumn';
+$lang->resource->kanban->restoreColumn = 'restoreColumn';
+$lang->resource->kanban->setColumn = 'setColumn';
+$lang->resource->kanban->setWIP = 'setWIP';
+$lang->resource->kanban->sortColumn = 'sortColumn';
+$lang->resource->kanban->deleteColumn = 'deleteColumn';
+$lang->resource->kanban->createCard = 'createCard';
+$lang->resource->kanban->editCard = 'editCard';
+$lang->resource->kanban->viewCard = 'viewCard';
+$lang->resource->kanban->sortCard = 'sortCard';
+$lang->resource->kanban->archiveCard = 'archiveCard';
+$lang->resource->kanban->assigntoCard = 'assigntoCard';
+//$lang->resource->kanban->copyCard = 'copyCard';
+$lang->resource->kanban->deleteCard = 'deleteCard';
+$lang->resource->kanban->moveCard = 'moveCard';
+$lang->resource->kanban->setCardColor = 'setCardColor';
+$lang->resource->kanban->laneMove = 'laneMove';
+$lang->resource->kanban->cardsSort = 'cardsSort';
+$lang->resource->kanban->viewArchivedColumn = 'viewArchivedColumn';
+$lang->resource->kanban->viewArchivedCard = 'viewArchivedCard';
+$lang->resource->kanban->restoreCard = 'restoreCard';
+$lang->resource->kanban->setLaneHeight = 'setLaneHeight';
+
+$lang->kanban->methodOrder[5] = 'space';
+$lang->kanban->methodOrder[10] = 'createSpace';
+$lang->kanban->methodOrder[15] = 'editSpace';
+$lang->kanban->methodOrder[20] = 'closeSpace';
+$lang->kanban->methodOrder[25] = 'deleteSpace';
+$lang->kanban->methodOrder[30] = 'sortSpace';
+$lang->kanban->methodOrder[35] = 'create';
+$lang->kanban->methodOrder[40] = 'edit';
+$lang->kanban->methodOrder[45] = 'view';
+$lang->kanban->methodOrder[50] = 'close';
+$lang->kanban->methodOrder[55] = 'delete';
+$lang->kanban->methodOrder[60] = 'createRegion';
+$lang->kanban->methodOrder[65] = 'editRegion';
+$lang->kanban->methodOrder[70] = 'sortRegion';
+$lang->kanban->methodOrder[72] = 'sortGroup';
+$lang->kanban->methodOrder[75] = 'deleteRegion';
+$lang->kanban->methodOrder[80] = 'createLane';
+$lang->kanban->methodOrder[85] = 'setLane';
+$lang->kanban->methodOrder[90] = 'sortLane';
+$lang->kanban->methodOrder[95] = 'deleteLane';
+$lang->kanban->methodOrder[100] = 'createColumn';
+$lang->kanban->methodorder[105] = 'splitColumn';
+$lang->kanban->methodorder[110] = 'restoreColumn';
+$lang->kanban->methodOrder[115] = 'setColumn';
+$lang->kanban->methodOrder[120] = 'setWIP';
+$lang->kanban->methodOrder[125] = 'sortColumn';
+$lang->kanban->methodOrder[130] = 'deleteColumn';
+$lang->kanban->methodOrder[135] = 'createCard';
+$lang->kanban->methodOrder[140] = 'editCard';
+$lang->kanban->methodOrder[145] = 'viewCard';
+$lang->kanban->methodOrder[150] = 'sortCard';
+$lang->kanban->methodOrder[155] = 'archivedCard';
+//$lang->kanban->methodOrder[160] = 'copyCard';
+$lang->kanban->methodOrder[165] = 'deleteCard';
+$lang->kanban->methodOrder[170] = 'assigntoCard';
+$lang->kanban->methodOrder[175] = 'moveCard';
+$lang->kanban->methodOrder[180] = 'setCardColor';
+$lang->kanban->methodOrder[185] = 'laneMove';
+$lang->kanban->methodorder[190] = 'cardsSort';
+$lang->kanban->methodOrder[195] = 'viewArchivedColumn';
+$lang->kanban->methodorder[200] = 'viewArchivedCard';
+$lang->kanban->methodorder[205] = 'archiveColumn';
+$lang->kanban->methodorder[210] = 'restoreCard';
+$lang->kanban->methodorder[215] = 'setLaneHeight';
+
+/* Execution. */
+$lang->resource->execution = new stdclass();
+$lang->resource->execution->view = 'view';
+$lang->resource->execution->browse = 'browse';
+$lang->resource->execution->create = 'createExec';
+$lang->resource->execution->edit = 'editAction';
+$lang->resource->execution->batchedit = 'batchEditAction';
+$lang->resource->execution->start = 'startAction';
+$lang->resource->execution->activate = 'activateAction';
+$lang->resource->execution->putoff = 'delayAction';
+$lang->resource->execution->suspend = 'suspendAction';
+$lang->resource->execution->close = 'closeAction';
+$lang->resource->execution->delete = 'deleteAB';
+$lang->resource->execution->task = 'task';
+$lang->resource->execution->grouptask = 'groupTask';
+$lang->resource->execution->importtask = 'importTask';
+$lang->resource->execution->importplanstories = 'importPlanStories';
+$lang->resource->execution->importBug = 'importBug';
+$lang->resource->execution->story = 'story';
+$lang->resource->execution->build = 'build';
+//$lang->resource->execution->qa = 'qa';
+$lang->resource->execution->testtask = 'testtask';
+$lang->resource->execution->testcase = 'testcase';
+$lang->resource->execution->bug = 'bug';
+$lang->resource->execution->testreport = 'testreport';
+$lang->resource->execution->burn = 'burn';
+$lang->resource->execution->computeBurn = 'computeBurnAction';
+$lang->resource->execution->fixFirst = 'fixFirst';
+$lang->resource->execution->burnData = 'burnData';
+$lang->resource->execution->team = 'teamAction';
+$lang->resource->execution->doc = 'doc';
+$lang->resource->execution->dynamic = 'dynamic';
+$lang->resource->execution->manageProducts = 'manageProducts';
+//$lang->resource->execution->manageChilds = 'manageChilds';
+$lang->resource->execution->manageMembers = 'manageMembers';
+$lang->resource->execution->unlinkMember = 'unlinkMember';
+$lang->resource->execution->linkStory = 'linkStory';
+$lang->resource->execution->unlinkStory = 'unlinkStory';
+$lang->resource->execution->batchUnlinkStory = 'batchUnlinkStory';
+$lang->resource->execution->updateOrder = 'updateOrder';
+$lang->resource->execution->taskKanban = 'taskKanban';
+$lang->resource->execution->printKanban = 'printKanbanAction';
+$lang->resource->execution->tree = 'treeAction';
+$lang->resource->execution->treeTask = 'treeOnlyTask';
+$lang->resource->execution->treeStory = 'treeOnlyStory';
+$lang->resource->execution->all = 'allExecutionAB';
+$lang->resource->execution->kanbanHideCols = 'kanbanHideCols';
+$lang->resource->execution->kanbanColsColor = 'kanbanColsColor';
+$lang->resource->execution->export = 'exportAction';
+$lang->resource->execution->storyKanban = 'storyKanban';
+$lang->resource->execution->storySort = 'storySort';
+$lang->resource->execution->whitelist = 'whitelist';
+$lang->resource->execution->addWhitelist = 'addWhitelist';
+$lang->resource->execution->unbindWhitelist = 'unbindWhitelist';
+$lang->resource->execution->storyEstimate = 'storyEstimate';
+$lang->resource->execution->executionkanban = 'kanbanAction';
+$lang->resource->execution->kanban = 'RDKanban';
+//if($config->systemMode == 'classic') $lang->resource->project->list = 'list';
+
+//$lang->execution->methodOrder[0] = 'index';
+//if($config->systemMode == 'classic') $lang->project->methodOrder[1] = 'list';
+$lang->execution->methodOrder[5] = 'view';
+$lang->execution->methodOrder[10] = 'browse';
+$lang->execution->methodOrder[15] = 'create';
+$lang->execution->methodOrder[20] = 'edit';
+$lang->execution->methodOrder[25] = 'batchedit';
+$lang->execution->methodOrder[30] = 'start';
+$lang->execution->methodOrder[35] = 'activate';
+$lang->execution->methodOrder[40] = 'putoff';
+$lang->execution->methodOrder[45] = 'suspend';
+$lang->execution->methodOrder[50] = 'close';
+$lang->execution->methodOrder[60] = 'delete';
+$lang->execution->methodOrder[65] = 'task';
+$lang->execution->methodOrder[70] = 'grouptask';
+$lang->execution->methodOrder[75] = 'importtask';
+$lang->execution->methodOrder[80] = 'importplanstories';
+$lang->execution->methodOrder[85] = 'importBug';
+$lang->execution->methodOrder[90] = 'story';
+$lang->execution->methodOrder[95] = 'build';
+$lang->execution->methodOrder[100] = 'qa';
+$lang->execution->methodOrder[105] = 'testcase';
+$lang->execution->methodOrder[110] = 'bug';
+$lang->execution->methodOrder[115] = 'testtask';
+$lang->execution->methodOrder[120] = 'testreport';
+$lang->execution->methodOrder[125] = 'burn';
+$lang->execution->methodOrder[130] = 'computeBurn';
+$lang->execution->methodOrder[135] = 'fixFirst';
+$lang->execution->methodOrder[140] = 'burnData';
+$lang->execution->methodOrder[145] = 'team';
+//$lang->execution->methodOrder[130] = 'doc';
+$lang->execution->methodOrder[150] = 'dynamic';
+$lang->execution->methodOrder[155] = 'manageProducts';
+$lang->execution->methodOrder[160] = 'manageMembers';
+$lang->execution->methodOrder[165] = 'unlinkMember';
+$lang->execution->methodOrder[170] = 'linkStory';
+$lang->execution->methodOrder[175] = 'unlinkStory';
+$lang->execution->methodOrder[180] = 'batchUnlinkStory';
+$lang->execution->methodOrder[185] = 'updateOrder';
+$lang->execution->methodOrder[190] = 'taskKanban';
+$lang->execution->methodOrder[195] = 'printKanban';
+$lang->execution->methodOrder[200] = 'kanbanHideCols';
+$lang->execution->methodOrder[205] = 'kanbanColsColor';
+$lang->execution->methodOrder[210] = 'tree';
+$lang->execution->methodOrder[215] = 'treeTask';
+$lang->execution->methodOrder[220] = 'treeStory';
+$lang->execution->methodOrder[225] = 'all';
+$lang->execution->methodOrder[230] = 'export';
+$lang->execution->methodOrder[235] = 'storyKanban';
+$lang->execution->methodOrder[240] = 'storySort';
+$lang->execution->methodOrder[245] = 'whitelist';
+$lang->execution->methodOrder[250] = 'addWhitelist';
+$lang->execution->methodOrder[255] = 'unbindWhitelist';
+$lang->execution->methodOrder[260] = 'storyEstimate';
+$lang->execution->methodOrder[265] = 'executionkanban';
+$lang->execution->methodOrder[270] = 'kanban';
+
+/* Task. */
+$lang->resource->task = new stdclass();
+$lang->resource->task->create = 'create';
+$lang->resource->task->edit = 'edit';
+$lang->resource->task->assignTo = 'assignAction';
+$lang->resource->task->start = 'startAction';
+$lang->resource->task->pause = 'pauseAction';
+$lang->resource->task->restart = 'restartAction';
+$lang->resource->task->finish = 'finishAction';
+$lang->resource->task->cancel = 'cancelAction';
+$lang->resource->task->close = 'closeAction';
+$lang->resource->task->batchCreate = 'batchCreate';
+$lang->resource->task->batchEdit = 'batchEdit';
+$lang->resource->task->batchClose = 'batchClose';
+$lang->resource->task->batchCancel = 'batchCancel';
+$lang->resource->task->batchAssignTo = 'batchAssignTo';
+$lang->resource->task->batchChangeModule = 'batchChangeModule';
+$lang->resource->task->activate = 'activateAction';
+$lang->resource->task->delete = 'deleteAction';
+$lang->resource->task->view = 'view';
+$lang->resource->task->export = 'exportAction';
+$lang->resource->task->confirmStoryChange = 'confirmStoryChange';
+$lang->resource->task->recordEstimate = 'recordEstimateAction';
+$lang->resource->task->editEstimate = 'editEstimate';
+$lang->resource->task->deleteEstimate = 'deleteEstimate';
+$lang->resource->task->report = 'reportChart';
+
+$lang->task->methodOrder[5] = 'create';
+$lang->task->methodOrder[10] = 'batchCreate';
+$lang->task->methodOrder[15] = 'batchEdit';
+$lang->task->methodOrder[20] = 'edit';
+$lang->task->methodOrder[25] = 'assignTo';
+$lang->task->methodOrder[30] = 'batchAssignTo';
+$lang->task->methodOrder[35] = 'start';
+$lang->task->methodOrder[40] = 'pause';
+$lang->task->methodOrder[45] = 'restart';
+$lang->task->methodOrder[50] = 'finish';
+$lang->task->methodOrder[55] = 'cancel';
+$lang->task->methodOrder[60] = 'close';
+$lang->task->methodOrder[65] = 'batchClose';
+$lang->task->methodOrder[70] = 'activate';
+$lang->task->methodOrder[75] = 'delete';
+$lang->task->methodOrder[80] = 'view';
+$lang->task->methodOrder[85] = 'export';
+$lang->task->methodOrder[90] = 'confirmStoryChange';
+$lang->task->methodOrder[95] = 'recordEstimate';
+$lang->task->methodOrder[100] = 'editEstimate';
+$lang->task->methodOrder[105] = 'deleteEstimate';
+$lang->task->methodOrder[110] = 'report';
+$lang->task->methodOrder[115] = 'batchChangeModule';
+
+/* Doc. */
+$lang->resource->doc = new stdclass();
+$lang->resource->doc->index = 'index';
+$lang->resource->doc->browse = 'browse';
+$lang->resource->doc->createLib = 'createLib';
+$lang->resource->doc->editLib = 'editLib';
+$lang->resource->doc->deleteLib = 'deleteLib';
+$lang->resource->doc->create = 'create';
+$lang->resource->doc->view = 'view';
+$lang->resource->doc->edit = 'edit';
+$lang->resource->doc->delete = 'delete';
+$lang->resource->doc->deleteFile = 'deleteFile';
+$lang->resource->doc->allLibs = 'allLibs';
+$lang->resource->doc->objectLibs = 'objectLibs';
+$lang->resource->doc->collect = 'collectAction';
+$lang->resource->doc->tableContents = 'tableContents';
+$lang->resource->doc->showFiles = 'showFiles';
+
+$lang->doc->methodOrder[0] = 'index';
+$lang->doc->methodOrder[5] = 'browse';
+$lang->doc->methodOrder[10] = 'createLib';
+$lang->doc->methodOrder[15] = 'editLib';
+$lang->doc->methodOrder[20] = 'deleteLib';
+$lang->doc->methodOrder[25] = 'create';
+$lang->doc->methodOrder[30] = 'view';
+$lang->doc->methodOrder[35] = 'edit';
+$lang->doc->methodOrder[40] = 'delete';
+$lang->doc->methodOrder[45] = 'deleteFile';
+$lang->doc->methodOrder[50] = 'allLibs';
+$lang->doc->methodOrder[55] = 'objectLibs';
+$lang->doc->methodOrder[60] = 'collect';
+$lang->doc->methodOrder[65] = 'tableContents';
+$lang->doc->methodOrder[70] = 'showFiles';
+
+/* Mail. */
+$lang->resource->mail = new stdclass();
+$lang->resource->mail->index = 'index';
+$lang->resource->mail->detect = 'detectAction';
+$lang->resource->mail->edit = 'edit';
+$lang->resource->mail->save = 'saveAction';
+$lang->resource->mail->test = 'test';
+$lang->resource->mail->reset = 'resetAction';
+$lang->resource->mail->browse = 'browse';
+$lang->resource->mail->delete = 'delete';
+$lang->resource->mail->resend = 'resendAction';
+$lang->resource->mail->batchDelete = 'batchDelete';
+$lang->resource->mail->sendCloud = 'sendCloud';
+$lang->resource->mail->sendcloudUser = 'sendcloudUser';
+$lang->resource->mail->ztCloud = 'ztCloud';
+
+$lang->mail->methodOrder[5] = 'index';
+$lang->mail->methodOrder[10] = 'detect';
+$lang->mail->methodOrder[15] = 'edit';
+$lang->mail->methodOrder[20] = 'save';
+$lang->mail->methodOrder[25] = 'test';
+$lang->mail->methodOrder[30] = 'reset';
+$lang->mail->methodOrder[35] = 'browse';
+$lang->mail->methodOrder[40] = 'delete';
+$lang->mail->methodOrder[45] = 'batchDelete';
+$lang->mail->methodOrder[50] = 'resend';
+$lang->mail->methodOrder[55] = 'sendCloud';
+$lang->mail->methodOrder[60] = 'sendcloudUser';
+$lang->mail->methodOrder[65] = 'ztCloud';
+
+/* Custom. */
+$lang->resource->custom = new stdclass();
+$lang->resource->custom->index = 'index';
+$lang->resource->custom->set = 'set';
+$lang->resource->custom->product = 'product';
+$lang->resource->custom->execution = 'execution';
+$lang->resource->custom->restore = 'restore';
+$lang->resource->custom->flow = 'flow';
+$lang->resource->custom->working = 'working';
+$lang->resource->custom->setPublic = 'setPublic';
+$lang->resource->custom->timezone = 'timezone';
+$lang->resource->custom->setStoryConcept = 'setStoryConcept';
+$lang->resource->custom->editStoryConcept = 'editStoryConcept';
+$lang->resource->custom->browseStoryConcept = 'browseStoryConcept';
+$lang->resource->custom->setDefaultConcept = 'setDefaultConcept';
+$lang->resource->custom->deleteStoryConcept = 'deleteStoryConcept';
+
+$lang->custom->methodOrder[5] = 'index';
+$lang->custom->methodOrder[10] = 'set';
+$lang->custom->methodOrder[15] = 'product';
+$lang->custom->methodOrder[20] = 'execution';
+$lang->custom->methodOrder[25] = 'restore';
+$lang->custom->methodOrder[30] = 'flow';
+$lang->custom->methodOrder[35] = 'working';
+$lang->custom->methodOrder[40] = 'setPublic';
+$lang->custom->methodOrder[45] = 'timezone';
+$lang->custom->methodOrder[50] = 'setStoryConcept';
+$lang->custom->methodOrder[55] = 'editStoryConcept';
+$lang->custom->methodOrder[60] = 'browseStoryConcept';
+$lang->custom->methodOrder[65] = 'setDefaultConcept';
+$lang->custom->methodOrder[70] = 'deleteStoryConcept';
+
+$lang->resource->datatable = new stdclass();
+$lang->resource->datatable->setGlobal = 'setGlobal';
+
+$lang->datatable->methodOrder[5] = 'setGlobal';
+
+/* Company. */
+$lang->resource->company = new stdclass();
+$lang->resource->company->index = 'index';
+$lang->resource->company->browse = 'browse';
+$lang->resource->company->edit = 'edit';
+$lang->resource->company->view = 'view';
+$lang->resource->company->dynamic= 'dynamic';
+
+$lang->company->methodOrder[0] = 'index';
+$lang->company->methodOrder[5] = 'browse';
+$lang->company->methodOrder[15] = 'edit';
+$lang->company->methodOrder[25] = 'dynamic';
+
+/* Department. */
+$lang->resource->dept = new stdclass();
+$lang->resource->dept->browse = 'browse';
+$lang->resource->dept->updateOrder = 'updateOrder';
+$lang->resource->dept->manageChild = 'manageChild';
+$lang->resource->dept->edit = 'edit';
+$lang->resource->dept->delete = 'delete';
+
+$lang->dept->methodOrder[5] = 'browse';
+$lang->dept->methodOrder[10] = 'updateOrder';
+$lang->dept->methodOrder[15] = 'manageChild';
+$lang->dept->methodOrder[20] = 'edit';
+$lang->dept->methodOrder[25] = 'delete';
+
+/* Group. */
+$lang->resource->group = new stdclass();
+$lang->resource->group->browse = 'browse';
+$lang->resource->group->create = 'create';
+$lang->resource->group->edit = 'edit';
+$lang->resource->group->copy = 'copy';
+$lang->resource->group->delete = 'delete';
+$lang->resource->group->manageView = 'manageView';
+$lang->resource->group->managePriv = 'managePriv';
+$lang->resource->group->manageMember = 'manageMember';
+$lang->resource->group->manageProjectAdmin = 'manageProjectAdmin';
+
+$lang->group->methodOrder[5] = 'browse';
+$lang->group->methodOrder[10] = 'create';
+$lang->group->methodOrder[15] = 'edit';
+$lang->group->methodOrder[20] = 'copy';
+$lang->group->methodOrder[25] = 'delete';
+$lang->group->methodOrder[30] = 'managePriv';
+$lang->group->methodOrder[35] = 'manageMember';
+$lang->group->methodOrder[40] = 'manageProjectAdmin';
+
+/* User. */
+$lang->resource->user = new stdclass();
+$lang->resource->user->create = 'create';
+$lang->resource->user->batchCreate = 'batchCreate';
+$lang->resource->user->view = 'view';
+$lang->resource->user->edit = 'edit';
+$lang->resource->user->unlock = 'unlock';
+$lang->resource->user->delete = 'delete';
+$lang->resource->user->todo = 'todo';
+$lang->resource->user->story = 'story';
+$lang->resource->user->task = 'task';
+$lang->resource->user->bug = 'bug';
+$lang->resource->user->testTask = 'testTask';
+$lang->resource->user->testCase = 'testCase';
+$lang->resource->user->execution = 'execution';
+$lang->resource->user->dynamic = 'dynamic';
+$lang->resource->user->cropAvatar = 'cropAvatar';
+$lang->resource->user->profile = 'profile';
+$lang->resource->user->batchEdit = 'batchEdit';
+$lang->resource->user->unbind = 'unbind';
+$lang->resource->user->setPublicTemplate = 'setPublicTemplate';
+
+$lang->user->methodOrder[5] = 'create';
+$lang->user->methodOrder[7] = 'batchCreate';
+$lang->user->methodOrder[10] = 'view';
+$lang->user->methodOrder[15] = 'edit';
+$lang->user->methodOrder[20] = 'unlock';
+$lang->user->methodOrder[25] = 'delete';
+$lang->user->methodOrder[30] = 'todo';
+$lang->user->methodOrder[35] = 'task';
+$lang->user->methodOrder[40] = 'bug';
+$lang->user->methodOrder[45] = 'project';
+$lang->user->methodOrder[60] = 'dynamic';
+$lang->user->methodOrder[65] = 'cropAvatar';
+$lang->user->methodOrder[70] = 'profile';
+$lang->user->methodOrder[75] = 'batchEdit';
+$lang->user->methodOrder[80] = 'unbind';
+$lang->user->methodOrder[85] = 'setPublicTemplate';
+
+/* Tree. */
+$lang->resource->tree = new stdclass();
+$lang->resource->tree->browse = 'browse';
+$lang->resource->tree->browseTask = 'browseTask';
+$lang->resource->tree->updateOrder = 'updateOrder';
+$lang->resource->tree->manageChild = 'manageChild';
+$lang->resource->tree->edit = 'edit';
+$lang->resource->tree->fix = 'fix';
+$lang->resource->tree->delete = 'delete';
+
+$lang->tree->methodOrder[5] = 'browse';
+$lang->tree->methodOrder[10] = 'browseTask';
+$lang->tree->methodOrder[15] = 'updateOrder';
+$lang->tree->methodOrder[20] = 'manageChild';
+$lang->tree->methodOrder[25] = 'edit';
+$lang->tree->methodOrder[30] = 'delete';
+
+/* Search. */
+$lang->resource->search = new stdclass();
+$lang->resource->search->buildForm = 'buildForm';
+$lang->resource->search->buildQuery = 'buildQuery';
+$lang->resource->search->saveQuery = 'saveQuery';
+$lang->resource->search->deleteQuery = 'deleteQuery';
+$lang->resource->search->select = 'select';
+$lang->resource->search->index = 'index';
+$lang->resource->search->buildIndex = 'buildIndex';
+
+$lang->search->methodOrder[5] = 'buildForm';
+$lang->search->methodOrder[10] = 'buildQuery';
+$lang->search->methodOrder[15] = 'saveQuery';
+$lang->search->methodOrder[20] = 'deleteQuery';
+$lang->search->methodOrder[25] = 'select';
+$lang->search->methodOrder[30] = 'index';
+$lang->search->methodOrder[35] = 'buildIndex';
+
+/* Admin. */
+$lang->resource->admin = new stdclass();
+$lang->resource->admin->index = 'index';
+$lang->resource->admin->checkDB = 'checkDB';
+$lang->resource->admin->safe = 'safeIndex';
+$lang->resource->admin->checkWeak = 'checkWeak';
+$lang->resource->admin->sso = 'ssoAction';
+$lang->resource->admin->register = 'register';
+$lang->resource->admin->ztCompany = 'ztCompany';
+
+$lang->admin->methodOrder[0] = 'index';
+$lang->admin->methodOrder[5] = 'checkDB';
+$lang->admin->methodOrder[10] = 'safeIndex';
+$lang->admin->methodOrder[15] = 'checkWeak';
+$lang->admin->methodOrder[20] = 'sso';
+$lang->admin->methodOrder[25] = 'register';
+$lang->admin->methodOrder[30] = 'ztCompany';
+
+/* Extension. */
+$lang->resource->extension = new stdclass();
+$lang->resource->extension->browse = 'browseAction';
+$lang->resource->extension->obtain = 'obtain';
+$lang->resource->extension->structure = 'structureAction';
+$lang->resource->extension->install = 'install';
+$lang->resource->extension->uninstall = 'uninstallAction';
+$lang->resource->extension->activate = 'activateAction';
+$lang->resource->extension->deactivate = 'deactivateAction';
+$lang->resource->extension->upload = 'upload';
+$lang->resource->extension->erase = 'eraseAction';
+$lang->resource->extension->upgrade = 'upgrade';
+
+$lang->extension->methodOrder[5] = 'browse';
+$lang->extension->methodOrder[10] = 'obtain';
+$lang->extension->methodOrder[15] = 'structure';
+$lang->extension->methodOrder[20] = 'install';
+$lang->extension->methodOrder[25] = 'uninstall';
+$lang->extension->methodOrder[30] = 'activate';
+$lang->extension->methodOrder[35] = 'deactivate';
+$lang->extension->methodOrder[40] = 'upload';
+$lang->extension->methodOrder[45] = 'erase';
+$lang->extension->methodOrder[50] = 'upgrade';
+
+/* Webhook. */
+$lang->resource->webhook = new stdclass();
+$lang->resource->webhook->browse = 'list';
+$lang->resource->webhook->create = 'create';
+$lang->resource->webhook->edit = 'edit';
+$lang->resource->webhook->delete = 'delete';
+$lang->resource->webhook->log = 'logAction';
+$lang->resource->webhook->bind = 'bind';
+$lang->resource->webhook->chooseDept = 'chooseDept';
+
+$lang->webhook->methodOrder[5] = 'browse';
+$lang->webhook->methodOrder[10] = 'create';
+$lang->webhook->methodOrder[15] = 'edit';
+$lang->webhook->methodOrder[20] = 'delete';
+$lang->webhook->methodOrder[25] = 'log';
+$lang->webhook->methodOrder[30] = 'bind';
+$lang->webhook->methodOrder[35] = 'chooseDept';
+
+/* Others. */
+$lang->resource->file = new stdclass();
+$lang->resource->file->download = 'download';
+$lang->resource->file->edit = 'edit';
+$lang->resource->file->delete = 'delete';
+$lang->resource->file->uploadImages = 'uploadImages';
+$lang->resource->file->setPublic = 'setPublic';
+
+$lang->file->methodOrder[5] = 'download';
+$lang->file->methodOrder[10] = 'edit';
+$lang->file->methodOrder[15] = 'delete';
+$lang->file->methodOrder[20] = 'uploadImages';
+$lang->file->methodOrder[25] = 'setPublic';
+
+$lang->resource->misc = new stdclass();
+$lang->resource->misc->ping = 'ping';
+
+$lang->misc->methodOrder[5] = 'ping';
+
+$lang->resource->message = new stdclass();
+$lang->resource->message->index = 'index';
+$lang->resource->message->browser = 'browser';
+$lang->resource->message->setting = 'setting';
+
+$lang->message->methodOrder[5] = 'index';
+$lang->message->methodOrder[10] = 'browser';
+$lang->message->methodOrder[15] = 'setting';
+
+$lang->resource->action = new stdclass();
+$lang->resource->action->trash = 'trash';
+$lang->resource->action->undelete = 'undeleteAction';
+$lang->resource->action->hideOne = 'hideOneAction';
+$lang->resource->action->hideAll = 'hideAll';
+$lang->resource->action->comment = 'comment';
+$lang->resource->action->editComment = 'editComment';
+
+$lang->action->methodOrder[5] = 'trash';
+$lang->action->methodOrder[10] = 'undelete';
+$lang->action->methodOrder[15] = 'hideOne';
+$lang->action->methodOrder[20] = 'hideAll';
+$lang->action->methodOrder[25] = 'comment';
+$lang->action->methodOrder[30] = 'editComment';
+
+$lang->resource->backup = new stdclass();
+$lang->resource->backup->index = 'index';
+$lang->resource->backup->backup = 'backup';
+$lang->resource->backup->restore = 'restore';
+$lang->resource->backup->change = 'change';
+$lang->resource->backup->delete = 'delete';
+$lang->resource->backup->setting = 'settingAction';
+$lang->resource->backup->rmPHPHeader = 'rmPHPHeader';
+
+$lang->backup->methodOrder[5] = 'index';
+$lang->backup->methodOrder[10] = 'backup';
+$lang->backup->methodOrder[15] = 'restore';
+$lang->backup->methodOrder[20] = 'delete';
+$lang->backup->methodOrder[25] = 'setting';
+$lang->backup->methodOrder[30] = 'rmPHPHeader';
+
+$lang->resource->cron = new stdclass();
+$lang->resource->cron->index = 'index';
+$lang->resource->cron->turnon = 'turnon';
+$lang->resource->cron->create = 'createAction';
+$lang->resource->cron->edit = 'edit';
+$lang->resource->cron->toggle = 'toggle';
+$lang->resource->cron->delete = 'delete';
+$lang->resource->cron->openProcess = 'restart';
+
+$lang->cron->methodOrder[5] = 'index';
+$lang->cron->methodOrder[10] = 'turnon';
+$lang->cron->methodOrder[15] = 'create';
+$lang->cron->methodOrder[20] = 'edit';
+$lang->cron->methodOrder[25] = 'toggle';
+$lang->cron->methodOrder[30] = 'delete';
+$lang->cron->methodOrder[35] = 'openProcess';
+
+if($config->edition == 'biz' or $config->edition == 'max')
+{
+ /* My module. */
+ $lang->resource->my->effort = 'effort'; // pro effort
+
+ /* Pro effort */
+ $lang->resource->effort = new stdclass();
+ $lang->resource->effort->batchCreate = 'batchCreate';
+ $lang->resource->effort->createForObject = 'createForObject';
+ $lang->resource->effort->edit = 'edit';
+ $lang->resource->effort->batchEdit = 'batchEdit';
+ $lang->resource->effort->view = 'view';
+ $lang->resource->effort->delete = 'delete';
+ $lang->resource->effort->export = 'export';
+ $lang->resource->effort->calendar = 'calendar'; // pro calendar
+
+ /* Todo. */
+ $lang->resource->todo->calendar = 'calendar'; // pro calendar
+
+ /* Feedback. */
+ $lang->resource->feedback = new stdclass();
+ $lang->resource->feedback->index = 'index';
+ $lang->resource->feedback->create = 'create';
+ $lang->resource->feedback->edit = 'edit';
+ $lang->resource->feedback->browse = 'browse';
+ $lang->resource->feedback->view = 'view';
+ $lang->resource->feedback->comment = 'comment';
+ $lang->resource->feedback->delete = 'delete';
+ $lang->resource->feedback->close = 'closeAction';
+ $lang->resource->feedback->export = 'exportAction';
+
+ /* Faq. */
+ $lang->resource->faq = new stdclass();
+ $lang->resource->faq->browse = 'browse';
+
+ /* Attend */
+ $lang->resource->attend = new stdclass();
+ $lang->resource->attend->department = 'department';
+ $lang->resource->attend->company = 'company';
+ $lang->resource->attend->browseReview = 'browseReview';
+ $lang->resource->attend->review = 'review';
+ $lang->resource->attend->export = 'exportAction';
+ $lang->resource->attend->stat = 'reportAction';
+ $lang->resource->attend->saveStat = 'saveStatAction';
+ $lang->resource->attend->exportStat = 'exportStat';
+ $lang->resource->attend->detail = 'detailAction';
+ $lang->resource->attend->exportDetail = 'exportDetail';
+ $lang->resource->attend->settings = 'settings';
+ $lang->resource->attend->personalSettings = 'personalSettings';
+ $lang->resource->attend->setManager = 'setManager';
+
+ $lang->resource->attend->personal = 'personal';
+ $lang->resource->attend->edit = 'editAction';
+
+ $lang->attend->methodOrder[5] = 'department';
+ $lang->attend->methodOrder[10] = 'company';
+ $lang->attend->methodOrder[15] = 'browseReview';
+ $lang->attend->methodOrder[20] = 'review';
+ $lang->attend->methodOrder[25] = 'export';
+ $lang->attend->methodOrder[30] = 'stat';
+ $lang->attend->methodOrder[35] = 'saveStat';
+ $lang->attend->methodOrder[40] = 'exportStat';
+ $lang->attend->methodOrder[45] = 'detail';
+ $lang->attend->methodOrder[60] = 'exportDetail';
+ $lang->attend->methodOrder[65] = 'settings';
+ $lang->attend->methodOrder[70] = 'personalSettings';
+ $lang->attend->methodOrder[75] = 'setManager';
+
+ $lang->attend->methodOrder[80] = 'personal';
+ $lang->attend->methodOrder[85] = 'edit';
+
+ /* Holiday */
+ $lang->resource->holiday = new stdclass();
+ $lang->resource->holiday->create = 'createAction';
+ $lang->resource->holiday->edit = 'editAction';
+ $lang->resource->holiday->delete = 'deleteAction';
+
+ $lang->resource->holiday->browse = 'browse';
+
+ $lang->holiday->methodOrder[0] = 'browse';
+ $lang->holiday->methodOrder[5] = 'create';
+ $lang->holiday->methodOrder[10] = 'edit';
+ $lang->holiday->methodOrder[15] = 'delete';
+
+ /* Leave */
+ $lang->resource->leave = new stdclass();
+ $lang->resource->leave->browseReview = 'browseReview';
+ $lang->resource->leave->company = 'companyAction';
+ $lang->resource->leave->review = 'reviewAction';
+ $lang->resource->leave->export = 'exportAction';
+ $lang->resource->leave->setReviewer = 'setReviewerAction';
+ $lang->resource->leave->personalAnnual = 'personalAnnual';
+
+ $lang->resource->leave->personal = 'personal';
+ $lang->resource->leave->create = 'createAction';
+ $lang->resource->leave->edit = 'editAction';
+ $lang->resource->leave->delete = 'deleteAction';
+ $lang->resource->leave->view = 'viewAction';
+ $lang->resource->leave->switchstatus = 'switchstatus';
+ $lang->resource->leave->back = 'backAction';
+
+ $lang->leave->methodOrder[0] = 'browseReview';
+ $lang->leave->methodOrder[5] = 'company';
+ $lang->leave->methodOrder[10] = 'review';
+ $lang->leave->methodOrder[15] = 'export';
+ $lang->leave->methodOrder[20] = 'setReviewer';
+ $lang->leave->methodOrder[25] = 'personalAnnual';
+
+ $lang->leave->methodOrder[30] = 'personal';
+ $lang->leave->methodOrder[35] = 'create';
+ $lang->leave->methodOrder[40] = 'edit';
+ $lang->leave->methodOrder[45] = 'delete';
+ $lang->leave->methodOrder[50] = 'view';
+ $lang->leave->methodOrder[55] = 'switchstatus';
+ $lang->leave->methodOrder[60] = 'back';
+
+ /* Makeup */
+ $lang->resource->makeup = new stdclass();
+ $lang->resource->makeup->browseReview = 'browseReview';
+ $lang->resource->makeup->company = 'companyAction';
+ $lang->resource->makeup->review = 'reviewAction';
+ $lang->resource->makeup->export = 'exportAction';
+ $lang->resource->makeup->setReviewer = 'setReviewerAction';
+
+ $lang->resource->makeup->personal = 'personal';
+ $lang->resource->makeup->create = 'createAction';
+ $lang->resource->makeup->edit = 'editAction';
+ $lang->resource->makeup->view = 'viewAction';
+ $lang->resource->makeup->delete = 'deleteAction';
+ $lang->resource->makeup->switchstatus = 'switchstatus';
+
+ $lang->makeup->methodOrder[0] = 'browseReview';
+ $lang->makeup->methodOrder[5] = 'company';
+ $lang->makeup->methodOrder[10] = 'review';
+ $lang->makeup->methodOrder[15] = 'export';
+ $lang->makeup->methodOrder[20] = 'setReviewer';
+
+ $lang->makeup->methodOrder[25] = 'personal';
+ $lang->makeup->methodOrder[30] = 'create';
+ $lang->makeup->methodOrder[35] = 'edit';
+ $lang->makeup->methodOrder[40] = 'view';
+ $lang->makeup->methodOrder[45] = 'delete';
+ $lang->makeup->methodOrder[50] = 'switchstatus';
+
+ /* Overtime */
+ $lang->resource->overtime = new stdclass();
+ $lang->resource->overtime->browseReview = 'browseReview';
+ $lang->resource->overtime->company = 'companyAction';
+ $lang->resource->overtime->review = 'reviewAction';
+ $lang->resource->overtime->export = 'exportAction';
+ $lang->resource->overtime->setReviewer = 'setReviewerAction';
+
+ $lang->resource->overtime->personal = 'personal';
+ $lang->resource->overtime->create = 'createAction';
+ $lang->resource->overtime->edit = 'editAction';
+ $lang->resource->overtime->view = 'viewAction';
+ $lang->resource->overtime->delete = 'deleteAction';
+ $lang->resource->overtime->switchstatus = 'switchstatus';
+
+ $lang->overtime->methodOrder[0] = 'browseReview';
+ $lang->overtime->methodOrder[5] = 'company';
+ $lang->overtime->methodOrder[10] = 'review';
+ $lang->overtime->methodOrder[15] = 'export';
+ $lang->overtime->methodOrder[20] = 'setReviewer';
+
+ $lang->overtime->methodOrder[25] = 'personal';
+ $lang->overtime->methodOrder[30] = 'create';
+ $lang->overtime->methodOrder[35] = 'edit';
+ $lang->overtime->methodOrder[40] = 'view';
+ $lang->overtime->methodOrder[45] = 'delete';
+ $lang->overtime->methodOrder[50] = 'switchstatus';
+
+ /* Lieu */
+ $lang->resource->lieu = new stdclass();
+ $lang->resource->lieu->company = 'companyAction';
+ $lang->resource->lieu->browseReview = 'browseReviewAction';
+ $lang->resource->lieu->review = 'reviewAction';
+ $lang->resource->lieu->setReviewer = 'setReviewerAction';
+
+ $lang->resource->lieu->personal = 'personal';
+ $lang->resource->lieu->create = 'createAction';
+ $lang->resource->lieu->edit = 'editAction';
+ $lang->resource->lieu->delete = 'deleteAction';
+ $lang->resource->lieu->view = 'viewAction';
+ $lang->resource->lieu->switchstatus = 'switchstatus';
+
+ $lang->lieu->methodOrder[0] = 'company';
+ $lang->lieu->methodOrder[5] = 'browseReview';
+ $lang->lieu->methodOrder[10] = 'review';
+ $lang->lieu->methodOrder[15] = 'setReviewer';
+
+ $lang->lieu->methodOrder[20] = 'personal';
+ $lang->lieu->methodOrder[25] = 'create';
+ $lang->lieu->methodOrder[30] = 'edit';
+ $lang->lieu->methodOrder[35] = 'delete';
+ $lang->lieu->methodOrder[40] = 'view';
+ $lang->lieu->methodOrder[45] = 'switchstatus';
+
+ /* Ops */
+ $lang->resource->tree->editHost = 'editHost';
+ $lang->resource->tree->browsehost = 'groupMaintenance';
+
+ $lang->tree->methodOrder[35] = 'editHost';
+ $lang->host->methodOrder[40] = 'groupMaintenance';
+
+ $lang->resource->ops = new stdclass();
+ $lang->resource->ops->index = 'index';
+ $lang->resource->ops->setting = 'setting';
+
+ $lang->ops->methodOrder[5] = 'index';
+ $lang->ops->methodOrder[10] = 'setting';
+
+ $lang->resource->host = new stdclass();
+ $lang->resource->host->browse = 'browse';
+ $lang->resource->host->create = 'create';
+ $lang->resource->host->edit = 'editAction';
+ $lang->resource->host->view = 'view';
+ $lang->resource->host->delete = 'deleteAction';
+ $lang->resource->host->changeStatus = 'changeStatus';
+ $lang->resource->host->treemap = 'treemap';
+
+ $lang->host->methodOrder[5] = 'browse';
+ $lang->host->methodOrder[10] = 'create';
+ $lang->host->methodOrder[15] = 'edit';
+ $lang->host->methodOrder[20] = 'view';
+ $lang->host->methodOrder[25] = 'delete';
+ $lang->host->methodOrder[30] = 'changeStatus';
+ $lang->host->methodOrder[35] = 'treemap';
+
+ $lang->resource->serverroom = new stdclass();
+ $lang->resource->serverroom->browse = 'browse';
+ $lang->resource->serverroom->create = 'create';
+ $lang->resource->serverroom->edit = 'editAction';
+ $lang->resource->serverroom->view = 'view';
+ $lang->resource->serverroom->delete = 'delete';
+
+ $lang->serverroom->methodOrder[5] = 'browse';
+ $lang->serverroom->methodOrder[10] = 'create';
+ $lang->serverroom->methodOrder[15] = 'edit';
+ $lang->serverroom->methodOrder[20] = 'view';
+ $lang->serverroom->methodOrder[25] = 'delete';
+
+ $lang->resource->account = new stdclass();
+ $lang->resource->account->browse = 'browse';
+ $lang->resource->account->create = 'create';
+ $lang->resource->account->edit = 'editAction';
+ $lang->resource->account->view = 'view';
+ $lang->resource->account->delete = 'deleteAction';
+
+ $lang->account = new stdclass();
+ $lang->account->methodOrder[5] = 'browse';
+ $lang->account->methodOrder[10] = 'create';
+ $lang->account->methodOrder[15] = 'edit';
+ $lang->account->methodOrder[20] = 'view';
+ $lang->account->methodOrder[25] = 'delete';
+
+ $lang->resource->domain = new stdclass();
+ $lang->resource->domain->browse = 'browse';
+ $lang->resource->domain->create = 'create';
+ $lang->resource->domain->edit = 'editAction';
+ $lang->resource->domain->view = 'view';
+ $lang->resource->domain->delete = 'deleteAction';
+
+ $lang->domain = new stdclass();
+ $lang->domain->methodOrder[5] = 'browse';
+ $lang->domain->methodOrder[10] = 'create';
+ $lang->domain->methodOrder[15] = 'edit';
+ $lang->domain->methodOrder[20] = 'view';
+ $lang->domain->methodOrder[25] = 'delete';
+
+
+ $lang->resource->service = new stdclass();
+ $lang->resource->service->index = 'index';
+ $lang->resource->service->create = 'create';
+ $lang->resource->service->edit = 'edit';
+ $lang->resource->service->view = 'view';
+ $lang->resource->service->delete = 'delete';
+ $lang->resource->service->manage = 'manage';
+ $lang->resource->service->browse = 'browse';
+
+ $lang->service->methodOrder[5] = 'index';
+ $lang->service->methodOrder[10] = 'create';
+ $lang->service->methodOrder[15] = 'edit';
+ $lang->service->methodOrder[20] = 'view';
+ $lang->service->methodOrder[25] = 'delete';
+ $lang->service->methodOrder[30] = 'manage';
+ $lang->service->methodOrder[35] = 'browse';
+
+ $lang->resource->deploy = new stdclass();
+ $lang->resource->deploy->browse = 'browse';
+ $lang->resource->deploy->create = 'create';
+ $lang->resource->deploy->edit = 'editAction';
+ $lang->resource->deploy->delete = 'deleteAction';
+ $lang->resource->deploy->activate = 'activateAction';
+ $lang->resource->deploy->finish = 'finishAction';
+ $lang->resource->deploy->scope = 'scope';
+ $lang->resource->deploy->manageScope = 'manageScope';
+ $lang->resource->deploy->view = 'view';
+ $lang->resource->deploy->cases = 'casesAction';
+ $lang->resource->deploy->linkCases = 'linkCases';
+ $lang->resource->deploy->unlinkCase = 'unlinkCase';
+ $lang->resource->deploy->batchUnlinkCases = 'batchUnlinkCases';
+ $lang->resource->deploy->steps = 'steps';
+ $lang->resource->deploy->manageStep = 'manageStep';
+ $lang->resource->deploy->finishStep = 'finishStep';
+ $lang->resource->deploy->assignTo = 'assignAction';
+ $lang->resource->deploy->viewStep = 'viewStep';
+ $lang->resource->deploy->editStep = 'editStep';
+ $lang->resource->deploy->deleteStep = 'deleteStep';
+
+ $lang->service->methodOrder[5] = 'browse';
+ $lang->service->methodOrder[10] = 'create';
+ $lang->service->methodOrder[15] = 'edit';
+ $lang->service->methodOrder[20] = 'delete';
+ $lang->service->methodOrder[25] = 'activate';
+ $lang->service->methodOrder[30] = 'finish';
+ $lang->service->methodOrder[35] = 'scope';
+ $lang->service->methodOrder[40] = 'manageScope';
+ $lang->service->methodOrder[45] = 'view';
+ $lang->service->methodOrder[50] = 'cases';
+ $lang->service->methodOrder[55] = 'linkCases';
+ $lang->service->methodOrder[60] = 'unlinkCase';
+ $lang->service->methodOrder[65] = 'batchUnlinkCases';
+ $lang->service->methodOrder[70] = 'steps';
+ $lang->service->methodOrder[75] = 'manageStep';
+ $lang->service->methodOrder[80] = 'finishStep';
+ $lang->service->methodOrder[85] = 'assignTo';
+ $lang->service->methodOrder[90] = 'viewStep';
+ $lang->service->methodOrder[95] = 'editStep';
+ $lang->service->methodOrder[100] = 'deleteStep';
+
+ $lang->resource->doc->diff = 'diffAction';
+ $lang->resource->doc->catalog = 'catalogAction';
+
+ $lang->resource->my->review = 'review';
+
+ /* workflow */
+ $lang->resource->workflow = new stdclass();
+ $lang->resource->workflow->browseFlow = 'browseFlow';
+ $lang->resource->workflow->browseDB = 'browseDB';
+ $lang->resource->workflow->create = 'create';
+ $lang->resource->workflow->copy = 'copy';
+ $lang->resource->workflow->edit = 'edit';
+ $lang->resource->workflow->backup = 'backup';
+ $lang->resource->workflow->upgrade = 'upgradeAction';
+ $lang->resource->workflow->view = 'view';
+ $lang->resource->workflow->delete = 'delete';
+ $lang->resource->workflow->flowchart = 'flowchart';
+ $lang->resource->workflow->ui = 'ui';
+ $lang->resource->workflow->release = 'release';
+ $lang->resource->workflow->deactivate = 'deactivate';
+ $lang->resource->workflow->activate = 'activate';
+ $lang->resource->workflow->setJS = 'setJS';
+ $lang->resource->workflow->setCSS = 'setCSS';
+
+ $lang->workflow->methodOrder[5] = 'browseFlow';
+ $lang->workflow->methodOrder[10] = 'browseDB';
+ $lang->workflow->methodOrder[15] = 'create';
+ $lang->workflow->methodOrder[20] = 'copy';
+ $lang->workflow->methodOrder[25] = 'edit';
+ $lang->workflow->methodOrder[30] = 'backup';
+ $lang->workflow->methodOrder[35] = 'upgrade';
+ $lang->workflow->methodOrder[40] = 'view';
+ $lang->workflow->methodOrder[45] = 'delete';
+ $lang->workflow->methodOrder[50] = 'flowchart';
+ $lang->workflow->methodOrder[55] = 'ui';
+ $lang->workflow->methodOrder[60] = 'release';
+ $lang->workflow->methodOrder[65] = 'deactivate';
+ $lang->workflow->methodOrder[70] = 'activate';
+ $lang->workflow->methodOrder[75] = 'setJS';
+ $lang->workflow->methodOrder[80] = 'setCSS';
+
+ /* workflowfield */
+ $lang->resource->workflowfield = new stdclass();
+ $lang->resource->workflowfield->browse = 'browse';
+ $lang->resource->workflowfield->create = 'create';
+ $lang->resource->workflowfield->edit = 'edit';
+ $lang->resource->workflowfield->delete = 'delete';
+ $lang->resource->workflowfield->import = 'import';
+ $lang->resource->workflowfield->showImport = 'showImport';
+ $lang->resource->workflowfield->sort = 'sort';
+ $lang->resource->workflowfield->exportTemplate = 'exportTemplate';
+ $lang->resource->workflowfield->setValue = 'setValue';
+ $lang->resource->workflowfield->setExport = 'setExport';
+ $lang->resource->workflowfield->setSearch = 'setSearch';
+
+ $lang->workflowfield->methodOrder[5] = 'browse';
+ $lang->workflowfield->methodOrder[10] = 'create';
+ $lang->workflowfield->methodOrder[15] = 'edit';
+ $lang->workflowfield->methodOrder[20] = 'delete';
+ $lang->workflowfield->methodOrder[25] = 'sort';
+ $lang->workflowfield->methodOrder[30] = 'import';
+ $lang->workflowfield->methodOrder[35] = 'showImport';
+ $lang->workflowfield->methodOrder[40] = 'exportTemplate';
+ $lang->workflowfield->methodOrder[45] = 'setValue';
+ $lang->workflowfield->methodOrder[50] = 'setExport';
+ $lang->workflowfield->methodOrder[55] = 'setSearch';
+
+ /* workflowaction */
+ $lang->resource->workflowaction = new stdclass();
+ $lang->resource->workflowaction->browse = 'browse';
+ $lang->resource->workflowaction->create = 'create';
+ $lang->resource->workflowaction->edit = 'edit';
+ $lang->resource->workflowaction->view = 'view';
+ $lang->resource->workflowaction->delete = 'delete';
+ $lang->resource->workflowaction->sort = 'sort';
+ $lang->resource->workflowaction->setVerification = 'setVerification';
+ $lang->resource->workflowaction->setNotice = 'setNotice';
+ $lang->resource->workflowaction->setJS = 'setJS';
+ $lang->resource->workflowaction->setCSS = 'setCSS';
+
+ $lang->workflowaction->methodOrder[5] = 'browse';
+ $lang->workflowaction->methodOrder[10] = 'create';
+ $lang->workflowaction->methodOrder[15] = 'edit';
+ $lang->workflowaction->methodOrder[20] = 'view';
+ $lang->workflowaction->methodOrder[25] = 'delete';
+ $lang->workflowaction->methodOrder[30] = 'sort';
+ $lang->workflowaction->methodOrder[35] = 'setVerification';
+ $lang->workflowaction->methodOrder[40] = 'setNotice';
+ $lang->workflowaction->methodOrder[45] = 'setJS';
+ $lang->workflowaction->methodOrder[50] = 'setCSS';
+
+ /* workflowcondition */
+ $lang->resource->workflowcondition = new stdclass();
+ $lang->resource->workflowcondition->browse = 'browse';
+ $lang->resource->workflowcondition->create = 'create';
+ $lang->resource->workflowcondition->edit = 'edit';
+ $lang->resource->workflowcondition->delete = 'delete';
+
+ $lang->workflowcondition->methodOrder[5] = 'browse';
+ $lang->workflowcondition->methodOrder[10] = 'create';
+ $lang->workflowcondition->methodOrder[15] = 'edit';
+ $lang->workflowcondition->methodOrder[20] = 'delete';
+
+ /* workflowlayout */
+ $lang->resource->workflowlayout = new stdclass();
+ $lang->resource->workflowlayout->admin = 'admin';
+ $lang->resource->workflowlayout->block = 'block';
+
+ $lang->workflowlayout->methodOrder[5] = 'admin';
+ $lang->workflowlayout->methodOrder[10] = 'block';
+
+ /* workflowlinkage */
+ $lang->resource->workflowlinkage = new stdclass();
+ $lang->resource->workflowlinkage->browse = 'browse';
+ $lang->resource->workflowlinkage->create = 'create';
+ $lang->resource->workflowlinkage->edit = 'edit';
+ $lang->resource->workflowlinkage->delete = 'delete';
+
+ $lang->workflowlinkage->methodOrder[5] = 'browse';
+ $lang->workflowlinkage->methodOrder[10] = 'create';
+ $lang->workflowlinkage->methodOrder[15] = 'edit';
+ $lang->workflowlinkage->methodOrder[20] = 'delete';
+
+ /* workflowhook */
+ $lang->resource->workflowhook = new stdclass();
+ $lang->resource->workflowhook->browse = 'browse';
+ $lang->resource->workflowhook->create = 'create';
+ $lang->resource->workflowhook->edit = 'edit';
+ $lang->resource->workflowhook->delete = 'delete';
+
+ $lang->workflowhook->methodOrder[5] = 'browse';
+ $lang->workflowhook->methodOrder[10] = 'create';
+ $lang->workflowhook->methodOrder[15] = 'edit';
+ $lang->workflowhook->methodOrder[20] = 'delete';
+
+ /* workflowlabel */
+ $lang->resource->workflowlabel = new stdclass();
+ $lang->resource->workflowlabel->browse = 'browse';
+ $lang->resource->workflowlabel->create = 'create';
+ $lang->resource->workflowlabel->edit = 'edit';
+ $lang->resource->workflowlabel->delete = 'delete';
+ $lang->resource->workflowlabel->sort = 'sort';
+
+ $lang->workflowlabel->methodOrder[5] = 'browse';
+ $lang->workflowlabel->methodOrder[10] = 'create';
+ $lang->workflowlabel->methodOrder[15] = 'edit';
+ $lang->workflowlabel->methodOrder[20] = 'delete';
+ $lang->workflowlabel->methodOrder[25] = 'sort';
+
+ /* workflowrelation */
+ $lang->resource->workflowrelation = new stdclass();
+ $lang->resource->workflowrelation->admin = 'admin';
+
+ $lang->workflowrelation->methodOrder[5] = 'admin';
+
+ /* workflowreport*/
+ $lang->resource->workflowreport = new stdclass();
+ $lang->resource->workflowreport->browse = 'brow';
+ $lang->resource->workflowreport->create = 'create';
+ $lang->resource->workflowreport->edit = 'edit';
+ $lang->resource->workflowreport->delete = 'delete';
+ $lang->resource->workflowreport->sort = 'sort';
+
+ $lang->workflowreport->methodOrder[5] = 'browse';
+ $lang->workflowreport->methodOrder[10] = 'create';
+ $lang->workflowreport->methodOrder[15] = 'edit';
+ $lang->workflowreport->methodOrder[20] = 'delete';
+ $lang->workflowreport->methodOrder[25] = 'sort';
+
+ /* workflowdatasource */
+ $lang->resource->workflowdatasource = new stdclass();
+ $lang->resource->workflowdatasource->browse = 'browse';
+ $lang->resource->workflowdatasource->create = 'create';
+ $lang->resource->workflowdatasource->edit = 'edit';
+ $lang->resource->workflowdatasource->delete = 'delete';
+
+ $lang->workflowdatasource->methodOrder[5] = 'browse';
+ $lang->workflowdatasource->methodOrder[10] = 'create';
+ $lang->workflowdatasource->methodOrder[15] = 'edit';
+ $lang->workflowdatasource->methodOrder[20] = 'delete';
+
+ /* workflowrule */
+ $lang->resource->workflowrule = new stdclass();
+ $lang->resource->workflowrule->browse = 'browse';
+ $lang->resource->workflowrule->create = 'create';
+ $lang->resource->workflowrule->edit = 'edit';
+ $lang->resource->workflowrule->view = 'view';
+ $lang->resource->workflowrule->delete = 'delete';
+
+ $lang->workflowrule->methodOrder[5] = 'browse';
+ $lang->workflowrule->methodOrder[10] = 'create';
+ $lang->workflowrule->methodOrder[15] = 'edit';
+ $lang->workflowrule->methodOrder[20] = 'view';
+ $lang->workflowrule->methodOrder[25] = 'delete';
+
+ $lang->resource->workflow->browse = 'browseAction';
+ $lang->resource->workflow->release = 'releaseAction';
+ $lang->resource->workflow->deactivate = 'deactivateAction';
+ $lang->resource->workflow->activate = 'activateAction';
+ $lang->resource->workflow->setJS = 'setJSAction';
+ $lang->resource->workflow->setCSS = 'setCSSAction';
+
+ $lang->resource->workflowfield->browse = 'browseAction';
+
+ $lang->resource->workflowaction->browse = 'browseAction';
+ $lang->resource->workflowaction->setJS = 'setJSAction';
+ $lang->resource->workflowaction->setCSS = 'setCSSAction';
+}
+// include (dirname(__FILE__) . '/changelog.php');
diff --git a/extension/lite/group/ext/lang/zh-cn/lite.php b/extension/lite/group/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..71b1dad82e
--- /dev/null
+++ b/extension/lite/group/ext/lang/zh-cn/lite.php
@@ -0,0 +1,2 @@
+
+$(function()
+{
+ $('#submit').parent().append('');
+});
+
diff --git a/extension/lite/group/ext/view/create.html.php b/extension/lite/group/ext/view/create.html.php
new file mode 100644
index 0000000000..c37f04af1e
--- /dev/null
+++ b/extension/lite/group/ext/view/create.html.php
@@ -0,0 +1,45 @@
+
+ * @package group
+ * @version $Id: create.html.php 4129 2013-01-18 01:58:14Z wwccss $
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+
+
+
group->create;?>
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/group/ext/view/managepriv.lite.html.hook.php b/extension/lite/group/ext/view/managepriv.lite.html.hook.php
new file mode 100644
index 0000000000..956029a0d7
--- /dev/null
+++ b/extension/lite/group/ext/view/managepriv.lite.html.hook.php
@@ -0,0 +1,3 @@
+
diff --git a/extension/lite/kanban/ext/lang/zh-cn/lite.php b/extension/lite/kanban/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..109bc66527
--- /dev/null
+++ b/extension/lite/kanban/ext/lang/zh-cn/lite.php
@@ -0,0 +1,8 @@
+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'] = '已关闭';
diff --git a/extension/lite/kanban/ext/model/lite.php b/extension/lite/kanban/ext/model/lite.php
new file mode 100644
index 0000000000..e80d0834e3
--- /dev/null
+++ b/extension/lite/kanban/ext/model/lite.php
@@ -0,0 +1,174 @@
+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;
+}
+
diff --git a/extension/lite/kanban/ext/view/createexeclane.lite.html.hook.php b/extension/lite/kanban/ext/view/createexeclane.lite.html.hook.php
new file mode 100644
index 0000000000..7e2162f9bc
--- /dev/null
+++ b/extension/lite/kanban/ext/view/createexeclane.lite.html.hook.php
@@ -0,0 +1,7 @@
+
diff --git a/extension/lite/message/ext/config/lite.php b/extension/lite/message/ext/config/lite.php
new file mode 100644
index 0000000000..73cc06ad8d
--- /dev/null
+++ b/extension/lite/message/ext/config/lite.php
@@ -0,0 +1,32 @@
+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;
diff --git a/extension/lite/message/ext/lang/zh-cn/lite.php b/extension/lite/message/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..a295555b6d
--- /dev/null
+++ b/extension/lite/message/ext/lang/zh-cn/lite.php
@@ -0,0 +1,3 @@
+message->label->archived = '归档';
+$lang->message->label->deleted = '删除';
diff --git a/extension/lite/misc/ext/lang/zh-cn/lite.php b/extension/lite/misc/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..ed4665c62c
--- /dev/null
+++ b/extension/lite/misc/ext/lang/zh-cn/lite.php
@@ -0,0 +1,2 @@
+misc->zentao->service);
diff --git a/extension/lite/misc/ext/view/about.lite.html.hook.php b/extension/lite/misc/ext/view/about.lite.html.hook.php
new file mode 100644
index 0000000000..d9ce1f817c
--- /dev/null
+++ b/extension/lite/misc/ext/view/about.lite.html.hook.php
@@ -0,0 +1,3 @@
+
diff --git a/extension/lite/my/ext/view/effort.calendar.html.hook.php b/extension/lite/my/ext/view/effort.calendar.html.hook.php
new file mode 100644
index 0000000000..4fd5b074a8
--- /dev/null
+++ b/extension/lite/my/ext/view/effort.calendar.html.hook.php
@@ -0,0 +1,3 @@
+getExtensionRoot() . 'biz/my/ext/view/effort.calendar.html.hook.php';
+if(file_exists($calendarHookFile)) include $calendarHookFile;
diff --git a/extension/lite/my/ext/view/task.html.php b/extension/lite/my/ext/view/task.html.php
new file mode 100644
index 0000000000..b240a99e6d
--- /dev/null
+++ b/extension/lite/my/ext/view/task.html.php
@@ -0,0 +1,319 @@
+
+ * @package dashboard
+ * @version $Id: task.html.php 5101 2013-07-12 00:44:27Z chencongzhi520@gmail.com $
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . '/common/view/header.html.php';?>
+
+recTotal);?>
+rawMethod);?>
+
+
+ {$pager->recTotal}"; ?>
+ rawMethod == 'contribute'):?>
+ rawMethod, "mode=$mode&type=assignedTo"), "{$lang->my->taskMenu->assignedToMe}" . ($type == 'assignedTo' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'assignedTo' ? ' btn-active-text' : '') . "'");
+ echo html::a(inlink($app->rawMethod, "mode=$mode&type=openedBy"), "{$lang->my->taskMenu->openedByMe}" . ($type == 'openedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'openedBy' ? ' btn-active-text' : '') . "'");
+ echo html::a(inlink($app->rawMethod, "mode=$mode&type=finishedBy"), "{$lang->my->taskMenu->finishedByMe}" . ($type == 'finishedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'finishedBy' ? ' btn-active-text' : '') . "'");
+ echo html::a(inlink($app->rawMethod, "mode=$mode&type=closedBy"), "{$lang->my->taskMenu->closedByMe}" . ($type == 'closedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'closedBy' ? ' btn-active-text' : '') . "'");
+ echo html::a(inlink($app->rawMethod, "mode=$mode&type=canceledBy"), "{$lang->my->taskMenu->canceledByMe}" . ($type == 'canceledBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'canceledBy' ? ' btn-active-text' : '') . "'");
+ ?>
+
+
+
+
+
+
+app->getModuleRoot() . '/common/view/footer.html.php';?>
diff --git a/extension/lite/my/ext/view/todo.calendar.html.hook.php b/extension/lite/my/ext/view/todo.calendar.html.hook.php
new file mode 100644
index 0000000000..711e1b1184
--- /dev/null
+++ b/extension/lite/my/ext/view/todo.calendar.html.hook.php
@@ -0,0 +1,3 @@
+getExtensionRoot() . 'biz/my/ext/view/todo.calendar.html.hook.php';
+if(file_exists($calendarHookFile)) include $calendarHookFile;
diff --git a/extension/lite/personnel/ext/view/addwhitelist.lite.html.hook.php b/extension/lite/personnel/ext/view/addwhitelist.lite.html.hook.php
new file mode 100644
index 0000000000..04c55c7bb0
--- /dev/null
+++ b/extension/lite/personnel/ext/view/addwhitelist.lite.html.hook.php
@@ -0,0 +1,8 @@
+
+
diff --git a/extension/lite/product/ext/config/lite.php b/extension/lite/product/ext/config/lite.php
new file mode 100644
index 0000000000..14aec8c4a7
--- /dev/null
+++ b/extension/lite/product/ext/config/lite.php
@@ -0,0 +1,7 @@
+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']);
diff --git a/extension/lite/product/ext/control/browse.php b/extension/lite/product/ext/control/browse.php
new file mode 100644
index 0000000000..60aff52c61
--- /dev/null
+++ b/extension/lite/product/ext/control/browse.php
@@ -0,0 +1,188 @@
+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', "¶m=$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();
+ }
+}
diff --git a/extension/lite/product/ext/lang/zh-cn/lite.php b/extension/lite/product/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..e0e2eb20d7
--- /dev/null
+++ b/extension/lite/product/ext/lang/zh-cn/lite.php
@@ -0,0 +1,3 @@
+product->noModule = '您现在还没有目录信息';
+$lang->product->storySummary = "本页共 %s 个%s,预计 %s 个{$lang->hourCommon}。";
diff --git a/extension/lite/product/ext/model/getpairs.php b/extension/lite/product/ext/model/getpairs.php
new file mode 100644
index 0000000000..d09219a3e2
--- /dev/null
+++ b/extension/lite/product/ext/model/getpairs.php
@@ -0,0 +1,37 @@
+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;
+}
diff --git a/extension/lite/product/ext/view/browse.html.php b/extension/lite/product/ext/view/browse.html.php
new file mode 100644
index 0000000000..7920a0dc86
--- /dev/null
+++ b/extension/lite/product/ext/view/browse.html.php
@@ -0,0 +1,623 @@
+
+ * @package product
+ * @version $Id: browse.html.php 4909 2013-06-26 07:23:50Z chencongzhi520@gmail.com $
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . '/common/view/header.html.php';?>
+app->getModuleRoot() . '/common/view/datatable.fix.html.php';?>
+
+
+
+
+
+app->rawModule);?>
+app->tab == 'product' ? $product->type : '');?>
+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&" : '';
+?>
+
+
+app->getViewType() == 'xhtml'):?>
+
+
+ product->getByID($productID)->name ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ story->noStory : $lang->story->noRequirement;?>
+
+ createLink('story', 'create', "productID={$productID}&branch={$branch}&moduleID={$moduleID}&storyID=0&projectID=$projectID&bugID=0&planID=0&todoID=0&extra=&type=$storyType"), " " . $lang->story->createCommon, '', "class='btn btn-info' data-app='$from'");?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ execution->linkStory, "id='toTaskButton'", 'btn btn-primary');?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | story->title;?> |
+ story->link . $lang->execution->common;?> |
+
+
+
+
+
+
+ |
+ projectstory->confirm, 'data-dismiss="modal" id="confirmBtn"', 'btn btn-primary');?>
+ |
+
+
+
+
+
+
+
+
+app->getModuleRoot() . '/common/view/footer.html.php';?>
diff --git a/extension/lite/project/ext/control/execution.php b/extension/lite/project/ext/control/execution.php
new file mode 100644
index 0000000000..e989151d0c
--- /dev/null
+++ b/extension/lite/project/ext/control/execution.php
@@ -0,0 +1,36 @@
+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();
+ }
+}
diff --git a/extension/lite/project/ext/js/index/lite.js b/extension/lite/project/ext/js/index/lite.js
new file mode 100644
index 0000000000..ffa394f8b1
--- /dev/null
+++ b/extension/lite/project/ext/js/index/lite.js
@@ -0,0 +1,7 @@
+$('#cards').on('click', '.panel', function(e)
+{
+ if(!$(e.target).closest('.kanban-actions').length)
+ {
+ location.href = $(this).data('url');
+ }
+});
diff --git a/extension/lite/project/ext/lang/zh-cn/lite.php b/extension/lite/project/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..a7db7de1f1
--- /dev/null
+++ b/extension/lite/project/ext/lang/zh-cn/lite.php
@@ -0,0 +1,5 @@
+project->leftStories = '剩余目标';
+$lang->project->doingExecutions = '进行中的看板';
+
+$lang->project->aclList['private'] = "私有 (只有项目负责人、团队成员可访问)";
diff --git a/extension/lite/project/ext/view/batchedit.lite.html.hook.php b/extension/lite/project/ext/view/batchedit.lite.html.hook.php
new file mode 100644
index 0000000000..ab63b1d104
--- /dev/null
+++ b/extension/lite/project/ext/view/batchedit.lite.html.hook.php
@@ -0,0 +1,4 @@
+
diff --git a/extension/lite/project/ext/view/browse.html.php b/extension/lite/project/ext/view/browse.html.php
new file mode 100644
index 0000000000..e25fd4772f
--- /dev/null
+++ b/extension/lite/project/ext/view/browse.html.php
@@ -0,0 +1,26 @@
+
+ * @package project
+ * @version $Id: prjbrowse.html.php 4769 2013-05-05 07:24:21Z wwccss $
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . '/common/view/header.html.php';?>
+app->getModuleRoot() . '/common/view/datatable.fix.html.php';?>
+
+app->getModuleRoot() . '/project/view/browsebylist.html.php';?>
+app->getModuleRoot() . '/common/view/footer.html.php';?>
diff --git a/extension/lite/project/ext/view/browse.lite.html.hook.php b/extension/lite/project/ext/view/browse.lite.html.hook.php
new file mode 100644
index 0000000000..23515331d3
--- /dev/null
+++ b/extension/lite/project/ext/view/browse.lite.html.hook.php
@@ -0,0 +1,10 @@
+
diff --git a/extension/lite/project/ext/view/create.html.php b/extension/lite/project/ext/view/create.html.php
new file mode 100644
index 0000000000..0a61d1aab3
--- /dev/null
+++ b/extension/lite/project/ext/view/create.html.php
@@ -0,0 +1,148 @@
+
+ * @package project
+ * @version $Id: create.html.php 4769 2013-05-05 07:24:21Z wwccss $
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . 'common/view/header.html.php';?>
+app->getModuleRoot() . 'common/view/kindeditor.html.php';?>
+
+
+
+
+execution->weekend);?>
+project->errorSameProducts);?>
+project->errorSameBranches);?>
+project->longTime);?>
+
+
+
+project->create->requiredFields;?>
+
+
+
+
project->create;?>
+
+
+
+
+
+
+
+
+
+
+
+ project->aclList, $acl, "onclick='setWhite(this.value);'", 'block'));?>
+
+app->getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/project/ext/view/edit.lite.html.hook.php b/extension/lite/project/ext/view/edit.lite.html.hook.php
new file mode 100644
index 0000000000..46e8e1f046
--- /dev/null
+++ b/extension/lite/project/ext/view/edit.lite.html.hook.php
@@ -0,0 +1,7 @@
+
diff --git a/extension/lite/project/ext/view/execution.html.php b/extension/lite/project/ext/view/execution.html.php
new file mode 100644
index 0000000000..ba68cfbab0
--- /dev/null
+++ b/extension/lite/project/ext/view/execution.html.php
@@ -0,0 +1,136 @@
+
+ * @package execution
+ * @version $Id: index.html.php 5094 2013-07-10 08:46:15Z chencongzhi520@gmail.com $
+ */
+?>
+app->getModuleRoot() . '/common/view/header.html.php';?>
+app->getModuleRoot() . '/common/view/sortable.html.php';?>
+
+
+ project->featureBar as $label => $labelName)
+ {
+ $active = $status == $label ? 'btn-active-text' : '';
+ echo html::a($this->createLink('project', 'execution', "status=$label&projectID=$projectID"), '' . $labelName . ' ' . ($status == $label ? "" . (int)count($kanbanList) . '' : ''), '', "class='btn btn-link $active'");
+ }
+ ?>
+
+
+ ' . $lang->project->createKanban, '', 'class="btn btn-primary"');?>
+
+
+
+
+
+
+ execution->noExecution;?>
+
+ createLink('execution', 'create', "projectID=$projectID"), " " . $lang->execution->createKanban, '', "class='btn btn-info' data-app='project'");?>
+
+
+
+
+
+ $kanban):?>
+
id");?>'>
+
+
+
execution->statusList, $kanban->status);?>
+
name;?>
+ id])));?>
+
+
+
+ ", '', "data-toggle='dropdown' class='btn btn-link'");?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+app->getModuleRoot() . '/common/view/footer.html.php';?>
diff --git a/extension/lite/project/ext/view/kanban.lite.html.hook.php b/extension/lite/project/ext/view/kanban.lite.html.hook.php
new file mode 100644
index 0000000000..24132ddde3
--- /dev/null
+++ b/extension/lite/project/ext/view/kanban.lite.html.hook.php
@@ -0,0 +1,4 @@
+
diff --git a/extension/lite/project/ext/view/managemembers.html.php b/extension/lite/project/ext/view/managemembers.html.php
new file mode 100644
index 0000000000..3a04c0f871
--- /dev/null
+++ b/extension/lite/project/ext/view/managemembers.html.php
@@ -0,0 +1,145 @@
+app->getModuleRoot() . 'common/view/header.html.php';?>
+id);?>
+
+
+
+
+
+project->unlinkExecutionMembers);?>
+
+
+
+
+
+
+ |
+ |
+ days, "class='form-control'");?> |
+ execution->defaultWorkhours, "class='form-control'");?> |
+ team->limitedList, 'no');?> |
+
+ ", '', "onclick='addItem(this)' class='btn btn-link'");?>
+ ", '', "onclick='deleteItem(this)' class='btn btn-link'");?>
+ |
+
+
+
+app->getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/project/ext/view/team.html.php b/extension/lite/project/ext/view/team.html.php
new file mode 100644
index 0000000000..74c975c412
--- /dev/null
+++ b/extension/lite/project/ext/view/team.html.php
@@ -0,0 +1,96 @@
+
+app->getModuleRoot() . 'common/view/header.html.php';?>
+project->confirmUnlinkMember)?>
+user->error->noAccess)?>
+
+
+ project->teamMember;?>
+
+
+ createLink('tutorial', 'wizard', "module=project&method=manageMembers¶ms=$wizardParams"), " " . $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", " " . $lang->project->manageMembers, '', "class='btn btn-primary manage-team-btn'");
+ }
+ }
+ ?>
+
+
+
+
+
+
+ execution->noMembers;?>
+ user->admin) or empty($app->user->rights['rights']['my']['limited'])) && common::hasPriv('project', 'manageMembers')):?>
+ createLink('project', 'manageMembers', "projectID=$projectID"), " " . $lang->project->manageMembers, '', "class='btn btn-info'");?>
+
+
+
+
+
+
+
+app->getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/project/ext/view/view.lite.html.hook.php b/extension/lite/project/ext/view/view.lite.html.hook.php
new file mode 100644
index 0000000000..0021dca3f5
--- /dev/null
+++ b/extension/lite/project/ext/view/view.lite.html.hook.php
@@ -0,0 +1,5 @@
+
diff --git a/extension/lite/projectstory/ext/control/story.php b/extension/lite/projectstory/ext/control/story.php
new file mode 100644
index 0000000000..b71d6f24e9
--- /dev/null
+++ b/extension/lite/projectstory/ext/control/story.php
@@ -0,0 +1,8 @@
+fetch('product', 'browse', "productID=$productID&branch=$branch&browseType=$browseType¶m=$param&storyType=$storyType&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID&projectID=$projectID");
+ }
+}
diff --git a/extension/lite/projectstory/ext/lang/zh-cn/lite.php b/extension/lite/projectstory/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..89163e28fe
--- /dev/null
+++ b/extension/lite/projectstory/ext/lang/zh-cn/lite.php
@@ -0,0 +1,6 @@
+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']);
diff --git a/extension/lite/search/ext/config/lite.php b/extension/lite/search/ext/config/lite.php
new file mode 100644
index 0000000000..dd383a46bd
--- /dev/null
+++ b/extension/lite/search/ext/config/lite.php
@@ -0,0 +1,13 @@
+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);
diff --git a/extension/lite/search/ext/lang/zh-cn/lite.php b/extension/lite/search/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..7d7c6c1faf
--- /dev/null
+++ b/extension/lite/search/ext/lang/zh-cn/lite.php
@@ -0,0 +1,17 @@
+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']);
diff --git a/extension/lite/story/ext/config/lite.php b/extension/lite/story/ext/config/lite.php
new file mode 100644
index 0000000000..0f3a2aef87
--- /dev/null
+++ b/extension/lite/story/ext/config/lite.php
@@ -0,0 +1,21 @@
+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']);
diff --git a/extension/lite/story/ext/lang/zh-cn/lite.php b/extension/lite/story/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..d31133ed09
--- /dev/null
+++ b/extension/lite/story/ext/lang/zh-cn/lite.php
@@ -0,0 +1,8 @@
+story->module = '所属目录';
+$lang->story->parent = '父目标';
+$lang->story->legendSpec = '目标描述';
+$lang->story->children = '子目标';
+
+$lang->story->legendLifeTime = '目标的一生';
+$lang->story->legendProjectAndTask = '看板任务';
diff --git a/extension/lite/story/ext/model/lite.php b/extension/lite/story/ext/model/lite.php
new file mode 100644
index 0000000000..ad083b957f
--- /dev/null
+++ b/extension/lite/story/ext/model/lite.php
@@ -0,0 +1,10 @@
+config->vision == 'lite')
+ {
+ $execution = $this->loadModel('execution')->getById($executionID);
+ if($execution->project) $executionID = $execution->project;
+ }
+ return parent::getExecutionStoryPairs($executionID, $productID, $branch, $moduleIdList, $type, $status);
+}
diff --git a/extension/lite/story/ext/view/batchcreate.html.php b/extension/lite/story/ext/view/batchcreate.html.php
new file mode 100644
index 0000000000..1fcfb127be
--- /dev/null
+++ b/extension/lite/story/ext/view/batchcreate.html.php
@@ -0,0 +1,141 @@
+
+ * @package story
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . 'common/view/header.html.php';?>
+
+
+
lang->story->subdivide : $this->lang->story->batchCreate;?>
+
+ createLink('file', 'uploadImages', 'module=story¶ms=' . 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%'")?>
+
+
+
+ story->create->requiredFields) as $field)
+ {
+ if($field)
+ {
+ $requiredFields[$field] = '';
+ if(strpos(",{$config->story->list->customBatchCreateFields},", ",{$field},") !== false) $visibleFields[$field] = '';
+ }
+ }
+ unset($visibleFields['module']);
+ ?>
+
+
+
+
+
+app->getModuleRoot() . 'common/view/pastetext.html.php';?>
+app->getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/story/ext/view/batchedit.html.php b/extension/lite/story/ext/view/batchedit.html.php
new file mode 100644
index 0000000000..930f4e2b97
--- /dev/null
+++ b/extension/lite/story/ext/view/batchedit.html.php
@@ -0,0 +1,116 @@
+
+ * @package story
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . 'common/view/header.html.php';?>
+lang->story->dittoNotice);?>
+
+app->tab);?>
+
+
+
+
+ story->common . $lang->colon . $lang->story->batchEdit;?>
+
+
+
+
+
+
+
+app->getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/story/ext/view/change.lite.html.hook.php b/extension/lite/story/ext/view/change.lite.html.hook.php
new file mode 100644
index 0000000000..0d60003fee
--- /dev/null
+++ b/extension/lite/story/ext/view/change.lite.html.hook.php
@@ -0,0 +1,6 @@
+
diff --git a/extension/lite/story/ext/view/close.lite.html.hook.php b/extension/lite/story/ext/view/close.lite.html.hook.php
new file mode 100644
index 0000000000..e1c92f8639
--- /dev/null
+++ b/extension/lite/story/ext/view/close.lite.html.hook.php
@@ -0,0 +1,9 @@
+
diff --git a/extension/lite/story/ext/view/create.html.php b/extension/lite/story/ext/view/create.html.php
new file mode 100644
index 0000000000..1f6bfd7cfb
--- /dev/null
+++ b/extension/lite/story/ext/view/create.html.php
@@ -0,0 +1,195 @@
+
+ * @package story
+ * @version $Id: create.html.php 4902 2013-06-26 05:25:58Z wyd621@gmail.com $
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . 'common/view/header.html.php';?>
+app->getModuleRoot() . 'common/view/kindeditor.html.php';?>
+
+story->placeholder); ?>
+
+story->feedbackSource); ?>
+
+
+
+
+
+
+
+
story->create;?>
+
+
+
+
+
+story->module);?>
+
+
+app->getModuleRoot() . '/common/view/footer.html.php';?>
diff --git a/extension/lite/story/ext/view/edit.html.php b/extension/lite/story/ext/view/edit.html.php
new file mode 100644
index 0000000000..77db321046
--- /dev/null
+++ b/extension/lite/story/ext/view/edit.html.php
@@ -0,0 +1,191 @@
+
+ * @package story
+ * @version $Id: edit.html.php 4645 2013-04-11 08:32:09Z chencongzhi520@gmail.com $
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . 'common/view/header.html.php';?>
+app->getModuleRoot() . 'common/view/kindeditor.html.php';?>
+
+product);?>
+children));?>
+story->moveChildrenTips);?>
+app->rawModule);?>
+
+story->module);?>
+
+story->notice->reviewerNotEmpty);?>
+story->feedbackSource); ?>
+
+
+
+type);?>
+
+
+app->getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/story/ext/view/review.lite.html.hook.php b/extension/lite/story/ext/view/review.lite.html.hook.php
new file mode 100644
index 0000000000..13d0ce6107
--- /dev/null
+++ b/extension/lite/story/ext/view/review.lite.html.hook.php
@@ -0,0 +1,4 @@
+
diff --git a/extension/lite/story/ext/view/view.html.php b/extension/lite/story/ext/view/view.html.php
new file mode 100644
index 0000000000..d01e99d581
--- /dev/null
+++ b/extension/lite/story/ext/view/view.html.php
@@ -0,0 +1,359 @@
+
+ * @package story
+ * @version $Id: view.html.php 4952 2013-07-02 01:14:58Z chencongzhi520@gmail.com $
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . 'common/view/header.html.php';?>
+app->getModuleRoot() . 'common/view/kindeditor.html.php';?>
+session->storyList ? $app->session->storyList : $this->createLink('product', 'browse', "productID=$story->product");?>
+
+
+
+app->getViewType() == 'xhtml'):?>
+
+
+
+
+
+
+
+
+
+
+ app->rawModule == 'projectstory') $otherParam = "storyID=&projectID={$this->session->project}";
+ ?>
+ product}&branch={$story->branch}&moduleID={$story->module}&$otherParam&bugID=0&planID=0&todoID=0&extra=&type=$story->type", " " . $lang->story->create, '', "class='btn btn-primary' data-app='project'"); ?>
+
+
+
+
+app->getViewType() == 'xhtml'):?>
+
+
+
+
+
+
+
+
story->legendSpec;?>
+
spec;?>
+
+ fetch('file', 'printFiles', array('files' => $story->files, 'fieldset' => 'true', 'object' => $story));?>
+ createLink('action', 'comment', "objectType=story&objectID=$story->id");
+ ?>
+ children)):?>
+
+
lang->story->children;?>
+
+
+
+
+ | story->id;?> |
+ priAB;?> |
+ story->title;?> |
+ story->assignedTo;?> |
+ story->estimate;?> |
+ story->status;?> |
+ actions;?> |
+
+
+
+ children as $child):?>
+
+ | id;?> |
+
+ pri . "'>";
+ echo $child->pri == '0' ? '' : zget($this->lang->story->priList, $child->pri, $child->pri);
+ echo "";
+ ?>
+ |
+ id", '', true); ?>">title;?> |
+ assignedTo);?> |
+ estimate . $config->hourUnit;?> |
+ processStatus('story', $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');
+ ?>
+ |
+
+
+
+
+
+
+
+
+ printExtendFields($story, 'div', "position=left&inForm=0&inCell=1");?>
+ app->getViewType() != 'xhtml'):?>
+
app->getModuleRoot() . 'common/view/action.html.php';?>
+
+
+
+
+
";?>
+ deleted):?>
+ 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, "
" . $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', "
" . $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 "
";
+ 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');
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | story->module;?> |
+ 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¶m=$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();
+ ?>
+ |
+
+
+ | story->status;?> |
+ processStatus('story', $story);?> |
+
+
+ | story->pri;?> |
+ pri;?>' title='story->priList, $story->pri)?>'>story->priList, $story->pri)?> |
+
+
+ | story->estimate;?> |
+ estimate . $config->hourUnit;?> |
+
+
+ | story->keywords;?> |
+ keywords;?> |
+
+
+ | story->legendMailto;?> |
+ mailto); foreach($mailto as $account) {if(empty($account)) continue; echo "" . zget($users, trim($account)) . ' '; }?> |
+
+
+
+
+
+
+
+
+ | story->openedBy;?> |
+ openedBy) . $lang->at . $story->openedDate;?> |
+
+
+ | story->assignedTo;?> |
+ assignedTo) echo zget($users, $story->assignedTo) . $lang->at . $story->assignedDate;?> |
+
+
+
+ | story->reviewers;?> |
+
+ $result)
+ {
+ echo !empty($result) ? ' ' . zget($users, $reviewer) . '' : ' ' . zget($users, $reviewer) . '';
+ }
+ }
+ ?>
+ |
+
+
+
+ | story->reviewedDate;?> |
+ reviewedBy) echo $story->reviewedDate;?> |
+
+
+ | story->closedBy;?> |
+ closedBy) echo zget($users, $story->closedBy) . $lang->at . $story->closedDate;?> |
+
+
+ | story->closedReason;?> |
+
+ 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]);
+ }
+ ?>
+ |
+
+
+ | story->lastEditedBy;?> |
+ lastEditedBy) echo zget($users, $story->lastEditedBy) . $lang->at . $story->lastEditedDate;?> |
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tasks as $executionTasks)
+ {
+ foreach($executionTasks as $task)
+ {
+ if(!isset($executions[$task->execution])) continue;
+ $executionName = $executions[$task->execution];
+ $taskInfo = $task->id . ' ' . $this->lang->task->statusList[$task->status] . ' ' . $task->name;
+ $class = isonlybody() ? 'showinonlybody' : 'iframe';
+ echo "- " . 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'") . '
';
+ }
+ }
+ if(count($story->tasks) == 0)
+ {
+ foreach($story->executions as $executionID => $execution)
+ {
+ echo "- " . html::a($this->createLink('execution', 'browse', "executionID=$executionID"), $execution->name, '', "class='text-muted'") . '
';
+ }
+ }
+ ?>
+
+
+
+
+
+ printExtendFields($story, 'div', "position=right&inForm=0&inCell=1");?>
+
+
+app->getViewType() == 'xhtml'):?>
+
+
+
+
+
+
+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);
+?>
+
+app->getModuleRoot() . 'common/view/syntaxhighlighter.html.php';?>
+app->getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/task/ext/config/lite.php b/extension/lite/task/ext/config/lite.php
new file mode 100644
index 0000000000..c1eed44dc3
--- /dev/null
+++ b/extension/lite/task/ext/config/lite.php
@@ -0,0 +1,3 @@
+task->customBatchCreateFields .= ',lane,region';
+$config->task->custom->batchCreateFields .= ',lane,region';
diff --git a/extension/lite/task/ext/control/batchcreate.php b/extension/lite/task/ext/control/batchcreate.php
new file mode 100644
index 0000000000..5635763039
--- /dev/null
+++ b/extension/lite/task/ext/control/batchcreate.php
@@ -0,0 +1,47 @@
+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);
+ }
+}
diff --git a/extension/lite/task/ext/control/create.php b/extension/lite/task/ext/control/create.php
new file mode 100644
index 0000000000..ae73290144
--- /dev/null
+++ b/extension/lite/task/ext/control/create.php
@@ -0,0 +1,48 @@
+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);
+ }
+}
diff --git a/extension/lite/task/ext/lang/zh-cn/lite.php b/extension/lite/task/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..f64aabc677
--- /dev/null
+++ b/extension/lite/task/ext/lang/zh-cn/lite.php
@@ -0,0 +1,79 @@
+
+ * @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'] = '按任务状态统计';
diff --git a/extension/lite/task/ext/view/batchcreate.html.php b/extension/lite/task/ext/view/batchcreate.html.php
new file mode 100644
index 0000000000..85a5fdb90b
--- /dev/null
+++ b/extension/lite/task/ext/view/batchcreate.html.php
@@ -0,0 +1,252 @@
+
+ * @package task
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . '/common/view/header.html.php';?>
+app->getModuleRoot() . '/common/view/datepicker.html.php';?>
+
+task->addChildTask);?>
+
+
+
+
+
+ lang->colon;?>
+ task->batchCreateChildren;?>
+
+ task->batchCreate;?>
+
+
+ type != 'ops'):?>
+
+
+
+
+
+
+ createLink('custom', 'ajaxSaveCustomFields', 'module=task§ion=custom&key=batchCreateFields')?>
+ app->getModuleRoot() . '/common/view/customfield.html.php';?>
+
+
+ task->create->requiredFields) as $field)
+ {
+ if($field)
+ {
+ $requiredFields[$field] = '';
+ if(strpos(",{$config->task->customBatchCreateFields},", ",{$field},") !== false) $visibleFields[$field] = '';
+ }
+ }
+ $colspan = count($visibleFields) + 3;
+ ?>
+
+
+
+type);?>
+
+
+task->ditto);?>
+
+
+app->getModuleRoot() . '/common/view/pastetext.html.php';?>
+app->getModuleRoot() . '/common/view/footer.html.php';?>
diff --git a/extension/lite/task/ext/view/batchcreate.lite.html.hook.php b/extension/lite/task/ext/view/batchcreate.lite.html.hook.php
new file mode 100644
index 0000000000..235f859f04
--- /dev/null
+++ b/extension/lite/task/ext/view/batchcreate.lite.html.hook.php
@@ -0,0 +1,6 @@
+
diff --git a/extension/lite/task/ext/view/create.html.php b/extension/lite/task/ext/view/create.html.php
new file mode 100644
index 0000000000..9ef19f6d53
--- /dev/null
+++ b/extension/lite/task/ext/view/create.html.php
@@ -0,0 +1,354 @@
+
+ * @package task
+ * @version $Id: create.html.php 5090 2013-07-10 05:49:24Z zhujinyonging@gmail.com $
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . '/common/view/header.html.php';?>
+app->getModuleRoot() . '/common/view/kindeditor.html.php';?>
+app->getModuleRoot() . '/common/view/sortable.html.php';?>
+id));?>
+
+
+
+
+
+
+
+
task->create;?>
+
+ createLink('custom', 'ajaxSaveCustomFields', 'module=task§ion=custom&key=createFields')?>
+ app->getModuleRoot() . '/common/view/customfield.html.php';?>
+
+
+ task->create->requiredFields) as $field)
+ {
+ if($field and strpos($showFields, $field) === false) $showFields .= ',' . $field;
+ }
+ ?>
+
+
+
+
+
+ | ''), 0, "class='form-control chosen'");?> |
+ task->priList, '', "class='form-control chosen'");?> |
+
+
+ task->estStarted}'");?>
+ ~
+ task->deadline}'");?>
+
+ |
+ ''), '', "class='form-control chosen'");?> |
+ |
+
+
+
+
+
+ |
+
+
+
+isINT) and class_exists('common')) ? common::convert2Pinyin($stories) : array());?>
+
+id);?>
+
+app->getModuleRoot() . '/common/view/footer.html.php';?>
diff --git a/extension/lite/task/ext/view/create.lite.html.hook.php b/extension/lite/task/ext/view/create.lite.html.hook.php
new file mode 100644
index 0000000000..5b499a0677
--- /dev/null
+++ b/extension/lite/task/ext/view/create.lite.html.hook.php
@@ -0,0 +1,6 @@
+
diff --git a/extension/lite/task/ext/view/report.lite.html.hook.php b/extension/lite/task/ext/view/report.lite.html.hook.php
new file mode 100644
index 0000000000..45e56b68b8
--- /dev/null
+++ b/extension/lite/task/ext/view/report.lite.html.hook.php
@@ -0,0 +1,3 @@
+
diff --git a/extension/lite/task/ext/view/view.lite.html.hook.php b/extension/lite/task/ext/view/view.lite.html.hook.php
new file mode 100644
index 0000000000..7149e646d9
--- /dev/null
+++ b/extension/lite/task/ext/view/view.lite.html.hook.php
@@ -0,0 +1,3 @@
+
diff --git a/extension/lite/todo/ext/lang/zh-cn/lite.php b/extension/lite/todo/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..7b162f90ef
--- /dev/null
+++ b/extension/lite/todo/ext/lang/zh-cn/lite.php
@@ -0,0 +1,5 @@
+todo->typeList['task'] = '任务';
+
+unset($lang->todo->typeList['bug']);
+unset($lang->todo->typeList['testtask']);
diff --git a/extension/lite/todo/ext/view/batchcreate.lite.html.hook.php b/extension/lite/todo/ext/view/batchcreate.lite.html.hook.php
new file mode 100644
index 0000000000..f9ced5a133
--- /dev/null
+++ b/extension/lite/todo/ext/view/batchcreate.lite.html.hook.php
@@ -0,0 +1,8 @@
+';?>
+
diff --git a/extension/lite/todo/ext/view/calendar.html.php b/extension/lite/todo/ext/view/calendar.html.php
new file mode 100644
index 0000000000..1376e469df
--- /dev/null
+++ b/extension/lite/todo/ext/view/calendar.html.php
@@ -0,0 +1,460 @@
+
+ * @package calendar
+ * @version $Id$
+ * @link http://www.zentao.net
+ */
+?>
+getModuleRoot() . 'common/view/header.html.php';?>
+getExtensionRoot() . 'biz/common/ext/view/calendar.html.php';?>
+
+lang->side->more);?>
+todo->moduleList);?>
+
+
+ todo->all . " {$todoCount}", '', "class='btn btn-link'");?>
+
+ effort->all . " {$effortCount}", '', "class='btn btn-link'");?>
+
+
+
+ app->user->id}&orderBy=id_desc&date=_date_") . '")', " " . $lang->todo->export, '', "class='btn btn-link'");?>
+ " . $lang->todo->batchCreate, '', "class='btn btn-secondary' id='batchCreate'", '', true);?>
+ " . $lang->todo->create, '', "id='create' class='btn btn-primary iframe' data-width='80%'", '', 'true');?>
+
+
+
+
+
+ dao->select('id,account,date,name,status,assignedTo')->from(TABLE_TODO)
+ ->where('status')->in('wait,doing')
+ ->andWhere('type')->ne('cycle')
+ ->andWhere('date')->ne(date('Y-m-d'))
+ ->andWhere('assignedTo')->eq($this->app->user->account)
+ ->andWhere('vision')->eq($this->config->vision)
+ ->fetchAll();
+ $undoneTodos = array();
+ $futureTodos = array();
+ foreach($todos as $todo)
+ {
+ if($todo->date == '2030-01-01')
+ {
+ $futureTodos[$todo->id] = $todo->name;
+ }
+ else
+ {
+ $undoneTodos[$todo->id] = $todo->name;
+ }
+ }
+ ?>
+
+
+
+
+
+
+
+ $todo):?>
+ -
+ createLink('todo', 'view', "id=$id", 'html', true), $todo, '', "class='iframe todo-item' data-id='{$id}' data-type='todo' data-title='{$todo}' title='{$todo}' data-width='70%'");?>
+
+
+
+
+
+
+
+
+
+ $todo):?>
+ -
+ createLink('todo', 'view', "id=$id", 'html', true), $todo, '', "class='iframe todo-item' data-id='{$id}' data-type='todo' data-title='{$todo}' title='{$todo}' data-width='70%'");?>
+
+
+
+
+
+
+
+
+
+ $todo):?>
+
+ -
+
+ createLink('task', 'view', "id=$id", 'html', true), $todo, '', "class='iframe $class' data-id='{$id}' data-type='task' data-title='{$todo}' title='{$todo}' data-width='70%'");?>
+
+
+
+
+
+
+
+
+
+
+
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/todo/ext/view/create.lite.html.hook.php b/extension/lite/todo/ext/view/create.lite.html.hook.php
new file mode 100644
index 0000000000..b589a10995
--- /dev/null
+++ b/extension/lite/todo/ext/view/create.lite.html.hook.php
@@ -0,0 +1,6 @@
+
diff --git a/extension/lite/tree/ext/control/browsetask.php b/extension/lite/tree/ext/control/browsetask.php
new file mode 100644
index 0000000000..bcb80dfd4d
--- /dev/null
+++ b/extension/lite/tree/ext/control/browsetask.php
@@ -0,0 +1,11 @@
+lang->kanban->menu->execution['subModule'] = 'tree';
+ $this->lang->kanban->menu->story['subModule'] = '';
+ return parent::browseTask($rootID, $productID, $currentModuleID);
+ }
+}
diff --git a/extension/lite/tree/ext/lang/zh-cn/lite.php b/extension/lite/tree/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..858f831cdd
--- /dev/null
+++ b/extension/lite/tree/ext/lang/zh-cn/lite.php
@@ -0,0 +1,15 @@
+tree->allMenu = '所有目录';
+$lang->tree->manageMenu = '维护目录';
+
+global $app;
+if($app->rawModule == 'tree' and $app->rawMethod == 'browse')
+{
+ $lang->tree->edit = '编辑目录';
+ $lang->tree->delete = '删除目录';
+ $lang->tree->child = '子目录';
+ $lang->tree->manageStoryChild = '维护子目录';
+ $lang->tree->name = '目录名称';
+ $lang->tree->syncFromProduct = '复制目录';
+}
+if($app->rawModule == 'story') $lang->tree->manage = $lang->tree->manageMenu;
diff --git a/extension/lite/tree/ext/view/browsetask.html.php b/extension/lite/tree/ext/view/browsetask.html.php
new file mode 100644
index 0000000000..d3c5b3b5af
--- /dev/null
+++ b/extension/lite/tree/ext/view/browsetask.html.php
@@ -0,0 +1,266 @@
+
+ * @package tree
+ * @version $Id: browse.html.php 4796 2013-06-06 02:21:59Z zhujinyonging@gmail.com $
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . 'common/view/header.html.php';?>
+tab);?>
+
+
+
+
+
+
+
+
+
+app->getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/user/ext/lang/zh-cn/lite.php b/extension/lite/user/ext/lang/zh-cn/lite.php
new file mode 100644
index 0000000000..d2f5818794
--- /dev/null
+++ b/extension/lite/user/ext/lang/zh-cn/lite.php
@@ -0,0 +1,2 @@
+user->task = '任务';
diff --git a/extension/lite/user/ext/model/lite.php b/extension/lite/user/ext/model/lite.php
new file mode 100644
index 0000000000..8f74ddca58
--- /dev/null
+++ b/extension/lite/user/ext/model/lite.php
@@ -0,0 +1,106 @@
+dao->select('t1.*,t2.*')->from(TABLE_TEAM)->alias('t1')
+ ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.root = t2.id')
+ ->where('t1.type')->eq($type)
+ ->andWhere('t2.type')->in($objectType)
+ ->beginIF(strpos('doing|wait|suspended|closed', $status) !== false)->andWhere('status')->eq($status)->fi()
+ ->beginIF($status == 'done')->andWhere('status')->in('done,closed')->fi()
+ ->beginIF($status == 'undone')->andWhere('status')->notin('done,closed')->fi()
+ ->beginIF($status == 'openedbyme')->andWhere('openedBy')->eq($account)->fi()
+ ->beginIF($type == 'execution' and !$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->sprints)->fi()
+ ->beginIF($type == 'project' and !$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->projects)->fi()
+ ->andWhere('t1.account')->eq($account)
+ ->andWhere('t2.deleted')->eq(0)
+ ->andWhere('t2.vision')->eq($this->config->vision)
+ ->orderBy("t2.$orderBy")
+ ->page($pager)
+ ->fetchAll('root');
+
+ $objectIdList = array();
+ $projectIdList = array();
+ foreach($myObjectsList as $object)
+ {
+ $objectIdList[] = $object->id;
+ $projectIdList[] = $object->project;
+ }
+
+ /* Get all tasks and compute totalConsumed, totalLeft, totalWait, progress according to them. */
+ $hours = array();
+ $emptyHour = array('totalConsumed' => 0, 'totalLeft' => 0, 'progress' => 0, 'waitTasks' => 0, 'assignedToMeTasks' => 0, 'doneTasks' => 0, 'taskTotal' => 0);
+ $searchField = $type == 'project' ? 'project' : 'execution';
+ $tasks = $this->dao->select('id, project, execution, consumed, `left`, status, assignedTo,finishedBy')
+ ->from(TABLE_TASK)
+ ->where('parent')->lt(1)
+ ->andWhere($searchField)->in($objectIdList)->fi()
+ ->andWhere('deleted')->eq(0)
+ ->fetchGroup($searchField, 'id');
+
+ /* Compute totalEstimate, totalConsumed, totalLeft. */
+ foreach($tasks as $objectID => $objectTasks)
+ {
+ $hour = (object)$emptyHour;
+ $hour->taskTotal = count($objectTasks);
+ foreach($objectTasks as $task)
+ {
+ if($task->status == 'wait') $hour->waitTasks += 1;
+ if($task->finishedBy != '') $hour->doneTasks += 1;
+ if($task->status != 'cancel') $hour->totalConsumed += $task->consumed;
+ if($task->status != 'cancel' and $task->status != 'closed') $hour->totalLeft += $task->left;
+ if($task->assignedTo == $account) $hour->assignedToMeTasks += 1;
+ }
+ $hours[$objectID] = $hour;
+ }
+
+ /* Compute totalReal and progress. */
+ foreach($hours as $hour)
+ {
+ $hour->totalConsumed = round($hour->totalConsumed, 1);
+ $hour->totalLeft = round($hour->totalLeft, 1);
+ $hour->totalReal = $hour->totalConsumed + $hour->totalLeft;
+ $hour->progress = $hour->totalReal ? round($hour->totalConsumed / $hour->totalReal, 2) * 100 : 0;
+ }
+
+ $myObjects = array();
+ $projectList = $this->loadModel('project')->getByIdList($projectIdList);
+ foreach($myObjectsList as $object)
+ {
+ /* Judge whether the project or execution is delayed. */
+ if($object->status != 'done' and $object->status != 'closed' and $object->status != 'suspended')
+ {
+ $delay = helper::diffDate(helper::today(), $object->end);
+ if($delay > 0) $object->delay = $delay;
+ }
+
+ /* Process the hours. */
+ $object->progress = isset($hours[$object->id]) ? $hours[$object->id]->progress : 0;
+ $object->waitTasks = isset($hours[$object->id]) ? $hours[$object->id]->waitTasks : 0;
+ $object->doneTasks = isset($hours[$object->id]) ? $hours[$object->id]->doneTasks : 0;
+ $object->taskTotal = isset($hours[$object->id]) ? $hours[$object->id]->taskTotal : 0;
+ $object->totalConsumed = isset($hours[$object->id]) ? $hours[$object->id]->totalConsumed : 0;
+ $object->assignedToMeTasks = isset($hours[$object->id]) ? $hours[$object->id]->assignedToMeTasks : 0;
+
+ if($object->project)
+ {
+ $parentProject = zget($projectList, $object->project, '');
+ $object->projectName = $parentProject ? $parentProject->name : '';
+ }
+ $myObjects[$object->id] = $object;
+ }
+
+ return $myObjects;
+}
+
diff --git a/extension/lite/user/ext/view/dynamic.lite.html.hook.php b/extension/lite/user/ext/view/dynamic.lite.html.hook.php
new file mode 100644
index 0000000000..b8993f230c
--- /dev/null
+++ b/extension/lite/user/ext/view/dynamic.lite.html.hook.php
@@ -0,0 +1 @@
+
diff --git a/extension/lite/user/ext/view/execution.html.php b/extension/lite/user/ext/view/execution.html.php
new file mode 100644
index 0000000000..6b6c8d08f8
--- /dev/null
+++ b/extension/lite/user/ext/view/execution.html.php
@@ -0,0 +1,63 @@
+
+ * @package dashboard
+ * @version $Id: project.html.php 4129 2013-01-18 01:58:14Z wwccss $
+ * @link http://www.zentao.net
+ */
+?>
+app->getModuleRoot() . 'common/view/header.html.php';?>
+app->getModuleRoot() . 'common/view/tablesorter.html.php';?>
+app->getModuleRoot() . 'user/view/featurebar.html.php';?>
+
+
+
+ id}&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}"; ?>
+
+
+ | idAB);?> |
+ user->name);?> |
+ statusAB);?> |
+ team->role;?> |
+ execution->begin);?> |
+ execution->end);?> |
+ team->join;?> |
+ team->hours;?> |
+
+
+
+
+ createLink('execution', 'view', "executionID=$execution->id");?>
+ config->vision == 'lite') $executionLink = $this->createLink('execution', 'kanban', "kanbanID=$execution->id");?>
+
+ | id);?> |
+
+ maxVersion)):?>
+ user->executionTypeList, $execution->type);?>
+
+ name);?>
+ |
+ delay)):?>
+ execution->delayed;?> |
+
+ processStatus('execution', $execution);?> |
+
+ role;?> |
+ begin;?> |
+ end;?> |
+ join;?> |
+ hours;?> |
+
+
+
+
+
+
+
+
+
+app->getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/user/ext/view/execution.lite.html.hook.php b/extension/lite/user/ext/view/execution.lite.html.hook.php
new file mode 100644
index 0000000000..b8993f230c
--- /dev/null
+++ b/extension/lite/user/ext/view/execution.lite.html.hook.php
@@ -0,0 +1 @@
+
diff --git a/extension/lite/user/ext/view/featurebar.lite.html.hook.php b/extension/lite/user/ext/view/featurebar.lite.html.hook.php
new file mode 100644
index 0000000000..bf6b7bc5e2
--- /dev/null
+++ b/extension/lite/user/ext/view/featurebar.lite.html.hook.php
@@ -0,0 +1,6 @@
+
diff --git a/extension/lite/user/ext/view/profile.lite.html.hook.php b/extension/lite/user/ext/view/profile.lite.html.hook.php
new file mode 100644
index 0000000000..b8993f230c
--- /dev/null
+++ b/extension/lite/user/ext/view/profile.lite.html.hook.php
@@ -0,0 +1 @@
+
diff --git a/extension/lite/user/ext/view/story.lite.html.hook.php b/extension/lite/user/ext/view/story.lite.html.hook.php
new file mode 100644
index 0000000000..b8993f230c
--- /dev/null
+++ b/extension/lite/user/ext/view/story.lite.html.hook.php
@@ -0,0 +1 @@
+
diff --git a/extension/lite/user/ext/view/task.lite.html.hook.php b/extension/lite/user/ext/view/task.lite.html.hook.php
new file mode 100644
index 0000000000..b8993f230c
--- /dev/null
+++ b/extension/lite/user/ext/view/task.lite.html.hook.php
@@ -0,0 +1 @@
+
diff --git a/extension/lite/user/ext/view/todo.lite.html.hook.php b/extension/lite/user/ext/view/todo.lite.html.hook.php
new file mode 100644
index 0000000000..b8993f230c
--- /dev/null
+++ b/extension/lite/user/ext/view/todo.lite.html.hook.php
@@ -0,0 +1 @@
+
diff --git a/extension/lite/user/ext/view/todocalendar.lite.html.hook.php b/extension/lite/user/ext/view/todocalendar.lite.html.hook.php
new file mode 100644
index 0000000000..b8993f230c
--- /dev/null
+++ b/extension/lite/user/ext/view/todocalendar.lite.html.hook.php
@@ -0,0 +1 @@
+
diff --git a/extension/lite/webhook/ext/view/create.lite.html.hook.php b/extension/lite/webhook/ext/view/create.lite.html.hook.php
new file mode 100644
index 0000000000..20aa1bea40
--- /dev/null
+++ b/extension/lite/webhook/ext/view/create.lite.html.hook.php
@@ -0,0 +1,7 @@
+
diff --git a/extension/lite/workflow/ext/view/browse.flow.html.hook.php b/extension/lite/workflow/ext/view/browse.flow.html.hook.php
new file mode 100644
index 0000000000..2dbe26bf06
--- /dev/null
+++ b/extension/lite/workflow/ext/view/browse.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflow/ext/view/browsedb.flow.html.hook.php b/extension/lite/workflow/ext/view/browsedb.flow.html.hook.php
new file mode 100644
index 0000000000..2dbe26bf06
--- /dev/null
+++ b/extension/lite/workflow/ext/view/browsedb.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflow/ext/view/copy.flow.html.hook.php b/extension/lite/workflow/ext/view/copy.flow.html.hook.php
new file mode 100644
index 0000000000..bb1ebdd750
--- /dev/null
+++ b/extension/lite/workflow/ext/view/copy.flow.html.hook.php
@@ -0,0 +1,4 @@
+
+app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflow/ext/view/create.flow.html.hook.php b/extension/lite/workflow/ext/view/create.flow.html.hook.php
new file mode 100644
index 0000000000..79974026e4
--- /dev/null
+++ b/extension/lite/workflow/ext/view/create.flow.html.hook.php
@@ -0,0 +1,3 @@
+
diff --git a/extension/lite/workflow/ext/view/edit.flow.html.hook.php b/extension/lite/workflow/ext/view/edit.flow.html.hook.php
new file mode 100644
index 0000000000..2dbe26bf06
--- /dev/null
+++ b/extension/lite/workflow/ext/view/edit.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflow/ext/view/flowchart.flow.html.hook.php b/extension/lite/workflow/ext/view/flowchart.flow.html.hook.php
new file mode 100644
index 0000000000..2dbe26bf06
--- /dev/null
+++ b/extension/lite/workflow/ext/view/flowchart.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflow/ext/view/release.flow.html.hook.php b/extension/lite/workflow/ext/view/release.flow.html.hook.php
new file mode 100644
index 0000000000..2dbe26bf06
--- /dev/null
+++ b/extension/lite/workflow/ext/view/release.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflow/ext/view/setcss.flow.html.hook.php b/extension/lite/workflow/ext/view/setcss.flow.html.hook.php
new file mode 100644
index 0000000000..2dbe26bf06
--- /dev/null
+++ b/extension/lite/workflow/ext/view/setcss.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflow/ext/view/setjs.flow.html.hook.php b/extension/lite/workflow/ext/view/setjs.flow.html.hook.php
new file mode 100644
index 0000000000..2dbe26bf06
--- /dev/null
+++ b/extension/lite/workflow/ext/view/setjs.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflow/ext/view/ui.flow.html.hook.php b/extension/lite/workflow/ext/view/ui.flow.html.hook.php
new file mode 100644
index 0000000000..2dbe26bf06
--- /dev/null
+++ b/extension/lite/workflow/ext/view/ui.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflow/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowaction/ext/view/browse.flow.html.hook.php b/extension/lite/workflowaction/ext/view/browse.flow.html.hook.php
new file mode 100644
index 0000000000..9a25285d22
--- /dev/null
+++ b/extension/lite/workflowaction/ext/view/browse.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowaction/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowaction/ext/view/create.flow.html.hook.php b/extension/lite/workflowaction/ext/view/create.flow.html.hook.php
new file mode 100644
index 0000000000..6c51eeb21c
--- /dev/null
+++ b/extension/lite/workflowaction/ext/view/create.flow.html.hook.php
@@ -0,0 +1,4 @@
+
+app->getExtensionRoot() . 'biz/workflowaction/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowaction/ext/view/edit.flow.html.hook.php b/extension/lite/workflowaction/ext/view/edit.flow.html.hook.php
new file mode 100644
index 0000000000..9a25285d22
--- /dev/null
+++ b/extension/lite/workflowaction/ext/view/edit.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowaction/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowaction/ext/view/setnotice.flow.html.hook.php b/extension/lite/workflowaction/ext/view/setnotice.flow.html.hook.php
new file mode 100644
index 0000000000..9a25285d22
--- /dev/null
+++ b/extension/lite/workflowaction/ext/view/setnotice.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowaction/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowdatasource/ext/view/browse.flow.html.hook.php b/extension/lite/workflowdatasource/ext/view/browse.flow.html.hook.php
new file mode 100644
index 0000000000..e029265b5e
--- /dev/null
+++ b/extension/lite/workflowdatasource/ext/view/browse.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowdatasource/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowdatasource/ext/view/create.flow.html.hook.php b/extension/lite/workflowdatasource/ext/view/create.flow.html.hook.php
new file mode 100644
index 0000000000..f4446f4d84
--- /dev/null
+++ b/extension/lite/workflowdatasource/ext/view/create.flow.html.hook.php
@@ -0,0 +1,4 @@
+
+app->getExtensionRoot() . 'biz/workflowdatasource/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowdatasource/ext/view/edit.flow.html.hook.php b/extension/lite/workflowdatasource/ext/view/edit.flow.html.hook.php
new file mode 100644
index 0000000000..e029265b5e
--- /dev/null
+++ b/extension/lite/workflowdatasource/ext/view/edit.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowdatasource/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowfield/ext/view/browse.flow.html.hook.php b/extension/lite/workflowfield/ext/view/browse.flow.html.hook.php
new file mode 100644
index 0000000000..11369cc5af
--- /dev/null
+++ b/extension/lite/workflowfield/ext/view/browse.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowfield/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowfield/ext/view/edit.flow.html.hook.php b/extension/lite/workflowfield/ext/view/edit.flow.html.hook.php
new file mode 100644
index 0000000000..11369cc5af
--- /dev/null
+++ b/extension/lite/workflowfield/ext/view/edit.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowfield/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowfield/ext/view/setexport.flow.html.hook.php b/extension/lite/workflowfield/ext/view/setexport.flow.html.hook.php
new file mode 100644
index 0000000000..11369cc5af
--- /dev/null
+++ b/extension/lite/workflowfield/ext/view/setexport.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowfield/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowfield/ext/view/setsearch.flow.html.hook.php b/extension/lite/workflowfield/ext/view/setsearch.flow.html.hook.php
new file mode 100644
index 0000000000..00b88e60ff
--- /dev/null
+++ b/extension/lite/workflowfield/ext/view/setsearch.flow.html.hook.php
@@ -0,0 +1 @@
+
diff --git a/extension/lite/workflowhook/ext/view/create.flow.html.hook.php b/extension/lite/workflowhook/ext/view/create.flow.html.hook.php
new file mode 100644
index 0000000000..abebb6d16b
--- /dev/null
+++ b/extension/lite/workflowhook/ext/view/create.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowhook/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowhook/ext/view/edit.flow.html.hook.php b/extension/lite/workflowhook/ext/view/edit.flow.html.hook.php
new file mode 100644
index 0000000000..abebb6d16b
--- /dev/null
+++ b/extension/lite/workflowhook/ext/view/edit.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowhook/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowlabel/ext/view/browse.flow.html.hook.php b/extension/lite/workflowlabel/ext/view/browse.flow.html.hook.php
new file mode 100644
index 0000000000..d32409775c
--- /dev/null
+++ b/extension/lite/workflowlabel/ext/view/browse.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowlabel/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowlayout/ext/view/admin.flow.html.hook.php b/extension/lite/workflowlayout/ext/view/admin.flow.html.hook.php
new file mode 100644
index 0000000000..038a427205
--- /dev/null
+++ b/extension/lite/workflowlayout/ext/view/admin.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowlayout/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowrelation/ext/view/admin.flow.html.hook.php b/extension/lite/workflowrelation/ext/view/admin.flow.html.hook.php
new file mode 100644
index 0000000000..09020f0aad
--- /dev/null
+++ b/extension/lite/workflowrelation/ext/view/admin.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowrelation/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowrule/ext/view/browse.flow.html.hook.php b/extension/lite/workflowrule/ext/view/browse.flow.html.hook.php
new file mode 100644
index 0000000000..06a563562d
--- /dev/null
+++ b/extension/lite/workflowrule/ext/view/browse.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowrule/ext/view/' . basename(__FILE__);?>
diff --git a/extension/lite/workflowrule/ext/view/view.flow.html.hook.php b/extension/lite/workflowrule/ext/view/view.flow.html.hook.php
new file mode 100644
index 0000000000..06a563562d
--- /dev/null
+++ b/extension/lite/workflowrule/ext/view/view.flow.html.hook.php
@@ -0,0 +1 @@
+app->getExtensionRoot() . 'biz/workflowrule/ext/view/' . basename(__FILE__);?>
diff --git a/framework/base/control.class.php b/framework/base/control.class.php
index 39758ad74c..5f693c0663 100644
--- a/framework/base/control.class.php
+++ b/framework/base/control.class.php
@@ -479,20 +479,14 @@ class baseControl
if(!empty($cssExtPath))
{
- $cssMethodExt = $cssExtPath['common'] . $methodName . DS;
- $cssCommonExt = $cssExtPath['common'] . 'common' . DS;
-
- $cssExtFiles = glob($cssCommonExt . $devicePrefix . '*.css');
- if(!empty($cssExtFiles) and is_array($cssExtFiles)) $css .= $this->getExtCSS($cssExtFiles);
-
- $cssExtFiles = glob($cssMethodExt . $devicePrefix . '*.css');
- if(!empty($cssExtFiles) and is_array($cssExtFiles)) $css .= $this->getExtCSS($cssExtFiles);
-
- if(!empty($cssExtPath['site']))
+ foreach($cssExtPath as $cssPath)
{
- $cssMethodExt = $cssExtPath['site'] . $methodName . DS;
- $cssCommonExt = $cssExtPath['site'] . 'common' . DS;
- $cssExtFiles = glob($cssCommonExt . $devicePrefix . '*.css');
+ if(empty($cssPath)) continue;
+
+ $cssMethodExt = $cssPath . $methodName . DS;
+ $cssCommonExt = $cssPath . 'common' . DS;
+
+ $cssExtFiles = glob($cssCommonExt . $devicePrefix . '*.css');
if(!empty($cssExtFiles) and is_array($cssExtFiles)) $css .= $this->getExtCSS($cssExtFiles);
$cssExtFiles = glob($cssMethodExt . $devicePrefix . '*.css');
@@ -579,19 +573,12 @@ class baseControl
if(!empty($jsExtPath))
{
- $jsMethodExt = $jsExtPath['common'] . $methodName . DS;
- $jsCommonExt = $jsExtPath['common'] . 'common' . DS;
-
- $jsExtFiles = glob($jsCommonExt . $this->devicePrefix . '*.js');
- if(!empty($jsExtFiles) and is_array($jsExtFiles)) foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile);
-
- $jsExtFiles = glob($jsMethodExt . $this->devicePrefix . '*.js');
- if(!empty($jsExtFiles) and is_array($jsExtFiles)) foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile);
-
- if(!empty($jsExtPath['site']))
+ foreach($jsExtPath as $jsPath)
{
- $jsMethodExt = $jsExtPath['site'] . $methodName . DS;
- $jsCommonExt = $jsExtPath['site'] . 'common' . DS;
+ if(empty($jsPath)) continue;
+
+ $jsMethodExt = $jsPath . $methodName . DS;
+ $jsCommonExt = $jsPath . 'common' . DS;
$jsExtFiles = glob($jsCommonExt . $this->devicePrefix . '*.js');
if(!empty($jsExtFiles) and is_array($jsExtFiles)) foreach($jsExtFiles as $jsFile) $js .= file_get_contents($jsFile);
@@ -771,6 +758,7 @@ class baseControl
*/
$this->app->setModuleName($moduleName);
$this->app->setMethodName($methodName);
+ $this->app->setControlFile();
if(!is_array($params)) parse_str($params, $params);
$this->app->params = $params;
@@ -793,8 +781,22 @@ class baseControl
* 设置公共扩展。
* set common extension.
*/
- $commonActionExtFile = $actionExtPath['common'] . strtolower($methodName) . '.php';
- $file2Included = file_exists($commonActionExtFile) ? $commonActionExtFile : $moduleControlFile;
+ $file2Included = $moduleControlFile;
+
+ $commonActionExtFile = $actionExtPath['custom'] . strtolower($methodName) . '.php';
+ if(file_exists($commonActionExtFile)) $file2Included = $commonActionExtFile;
+
+ if(!empty($actionExtPath['vision']))
+ {
+ $commonActionExtFile = $actionExtPath['vision'] . strtolower($methodName) . '.php';
+ if(file_exists($commonActionExtFile)) $file2Included = $commonActionExtFile;
+ }
+
+ if(!empty($actionExtPath['common']))
+ {
+ $commonActionExtFile = $actionExtPath['common'] . strtolower($methodName) . '.php';
+ if(file_exists($commonActionExtFile)) $file2Included = $commonActionExtFile;
+ }
if(!empty($actionExtPath['site']))
{
diff --git a/framework/base/helper.class.php b/framework/base/helper.class.php
index 808bd6dc93..89d65dbb6b 100644
--- a/framework/base/helper.class.php
+++ b/framework/base/helper.class.php
@@ -202,6 +202,21 @@ class baseHelper
return true;
}
+ /**
+ * 使用helper::importControl()来引入Control文件,不要直接使用include或者require.
+ * Using helper::importControl() to import a file, instead of include or require.
+ *
+ * @param string $moduleName.
+ * @static
+ * @access public
+ * @return bool
+ */
+ static public function importControl($moduleName)
+ {
+ global $app;
+ return helper::import($app->getModulePath($moduleName) . 'control.php');
+ }
+
/**
* 将数组或者列表转化成 IN( 'a', 'b') 的形式。
* Convert a list to IN('a', 'b') string.
diff --git a/framework/base/model.class.php b/framework/base/model.class.php
index 8e15c750a1..5057bde3b0 100644
--- a/framework/base/model.class.php
+++ b/framework/base/model.class.php
@@ -259,7 +259,8 @@ class baseModel
$extensionName = strtolower($extensionName);
$moduleExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'model');
if(!empty($moduleExtPath['site'])) $extensionFile = $moduleExtPath['site'] . 'class/' . $extensionName . '.class.php';
- if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['common'] . 'class/' . $extensionName . '.class.php';
+ if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['custom'] . 'class/' . $extensionName . '.class.php';
+ if(!file_exists($extensionFile)) $extensionFile = $moduleExtPath['common'] . 'class/' . $extensionName . '.class.php';
/* 设置扩展类的名字。Set the extension class name. */
$extensionClass = $extensionName . ucfirst($moduleName);
diff --git a/framework/base/router.class.php b/framework/base/router.class.php
index b4e9fdf481..fc6d9824c7 100644
--- a/framework/base/router.class.php
+++ b/framework/base/router.class.php
@@ -406,6 +406,9 @@ class baseRouter
if($this->config->framework->autoConnectDB) $this->connectDB();
if($this->config->framework->multiLanguage) $this->setClientLang();
+ $this->setEdition();
+ $this->setVision();
+
$needDetectDevice = zget($this->config->framework->detectDevice, $this->clientLang, false);
$this->clientDevice = $needDetectDevice ? $this->setClientDevice() : 'desktop';
@@ -665,6 +668,46 @@ class baseRouter
if(!empty($this->config->debug)) error_reporting(E_ALL & ~ E_STRICT);
}
+ /**
+ * 设置版本。
+ * Set edition.
+ *
+ * @access public
+ * @return void
+ */
+ public function setEdition()
+ {
+ if(isset($this->config->edition)) return $this->config->edition;
+
+ $edition = substr($this->config->version, 0, 3);
+ if(in_array($edition, array('pro', 'biz', 'max'))) return $this->config->edition = $edition;
+ $this->config->edition = 'open';
+ }
+
+ /**
+ * 设置vision。
+ * set Debug.
+ *
+ * @access public
+ * @return void
+ */
+ public function setVision()
+ {
+ $account = isset($_SESSION['user']) ? $_SESSION['user']->account : '';
+ if(empty($account) and isset($_POST['account'])) $account = $_POST['account'];
+ if(empty($account) and isset($_GET['account'])) $account = $_GET['account'];
+
+ $vision = '';
+ if($this->config->installed) $vision = $this->dbh->query("SELECT * FROM " . TABLE_CONFIG . " WHERE owner = '$account' AND `key` = 'vision' LIMIT 1")->fetch();
+ if($vision) $vision = $vision->value;
+ if(!empty($_SESSION['user']->visions) and empty($vision)) list($vision) = explode(',', $_SESSION['user']->visions);
+
+ list($defaultVision) = explode(',', trim($this->config->visions, ','));
+ if($vision and strpos($this->config->visions, ",{$vision},") === false) $vision = $defaultVision;
+
+ $this->config->vision = $vision ? $vision : $defaultVision;
+ }
+
/**
* 设置错误处理句柄。
* Set the error handler.
@@ -812,6 +855,18 @@ class baseRouter
return dirname($this->moduleRoot) . DS . $appName . DS;
}
+ /**
+ * 获取扩展根目录。
+ * Get the root of extension.
+ *
+ * @access public
+ * @return string
+ */
+ public function getExtensionRoot()
+ {
+ return $this->basePath . 'extension' . DS;
+ }
+
/**
* 获取$webRoot,即应用的路径。
* Get the $webRoot var.
@@ -1284,7 +1339,7 @@ class baseRouter
*/
public function setControlFile($exitIfNone = true)
{
- $this->controlFile = $this->moduleRoot . $this->moduleName . DS . 'control.php';
+ $this->controlFile = $this->getModulePath() . 'control.php';
if(file_exists($this->controlFile)) return true;
$this->triggerError("the control file $this->controlFile not found.", __FILE__, __LINE__, $exitIfNone);
}
@@ -1314,11 +1369,30 @@ class baseRouter
public function getModulePath($appName = '', $moduleName = '')
{
if($moduleName == '') $moduleName = $this->moduleName;
+ $moduleName = strtolower($moduleName);
if($this->checkModuleName($moduleName))
{
- $modulePath = $this->getModuleRoot($appName) . strtolower($moduleName) . DS;
- return $modulePath;
+ /* 1. 如果通用版本里有此模块,优先使用。 If module is in the open edition, use it. */
+ $modulePath = $this->getModuleRoot($appName) . $moduleName . DS;
+ if(is_dir($modulePath)) return $modulePath;
+
+ /* 2. 尝试查找商业版本是否有此模块。 Try to find the module in other editon. */
+ if($this->config->edition != 'open')
+ {
+ $modulePath = $this->getExtensionRoot() . $this->config->edition . DS . $moduleName . DS;
+ if(is_dir($modulePath)) return $modulePath;
+ }
+
+ /* 3. 如果设置过vision,尝试在vision中查找。 If vision is set, try to find the module in the vision. */
+ if($this->config->vision != 'rnd')
+ {
+ $modulePath = $this->getExtensionRoot() . $this->config->vision . DS . $moduleName . DS;
+ if(is_dir($modulePath)) return $modulePath;
+ }
+
+ /* 4. 最后尝试在定制开发中寻找。 Finally, try to find the module in the custom dir. */
+ return $this->getExtensionRoot() . 'custom' . DS . $moduleName . DS;
}
}
@@ -1340,14 +1414,17 @@ class baseRouter
/* 检查失败或者extensionLevel为0,直接返回空。If check failed or extensionLevel == 0, return empty array. */
if(!$this->checkModuleName($moduleName) or $this->config->framework->extensionLevel == 0) return array();
- /* When extensionLevel == 1. */
- $modulePath = $this->getModulePath($appName, $moduleName);
$paths = array();
- $paths['common'] = $modulePath . 'ext' . DS . $ext . DS;
+
+ /* When extensionLevel == 1. */
+ $paths['common'] = $this->config->edition != 'open' ? $this->getExtensionRoot() . $this->config->edition . DS . $moduleName . DS . 'ext' . DS . $ext . DS : '';
+ $paths['xuan'] = $this->getExtensionRoot() . 'xuan' . DS . $moduleName . DS . 'ext' . DS . $ext . DS;
+ $paths['vision'] = $this->config->vision == 'rnd' ? '' : $this->basePath . 'extension' . DS . $this->config->vision . DS . $moduleName . DS . 'ext' . DS . $ext . DS;
+ $paths['custom'] = $this->getExtensionRoot() . 'custom' . DS . $moduleName . DS . 'ext' . DS . $ext . DS;
if($this->config->framework->extensionLevel == 1) return $paths;
/* When extensionLevel == 2. */
- $paths['site'] = empty($this->siteCode) ? '' : $modulePath . 'ext' . DS . '_' . $this->siteCode . DS . $ext . DS;
+ $paths['site'] = empty($this->siteCode) ? '' : $this->getExtensionRoot() . $this->config->edition . DS . $moduleName . DS . 'ext' . DS . '_' . $this->siteCode . DS . $ext . DS;
return $paths;
}
@@ -1396,15 +1473,28 @@ class baseRouter
/* 如果扩展目录为空,不包含任何扩展文件。If there's no ext paths return false.*/
if(empty($moduleExtPaths)) return false;
- /* 如果extensionLevel == 2,且扩展文件存在,返回该站点扩展文件。If extensionLevel == 2 and site extensionFile exists, return it. */
+ /* 1. 如果extensionLevel == 2,且扩展文件存在,返回该站点扩展文件。 If extensionLevel == 2 and site extensionFile exists, return it. */
if($this->config->framework->extensionLevel == 2 and !empty( $moduleExtPaths['site']))
{
$this->extActionFile = $moduleExtPaths['site'] . $this->methodName . '.php';
if(file_exists($this->extActionFile)) return true;
}
- /* 然后再尝试寻找公共扩展文件。Then try to find the common extension file. */
+ /* 2. 尝试在定制开发目录寻找扩展文件。Then try to find the custom extension file. */
+ $this->extActionFile = $moduleExtPaths['custom'] . $this->methodName . '.php';
+ if(file_exists($this->extActionFile)) return true;;
+
+ /* 3. 如果设置过vision,尝试在vision中查找扩展文件。If vision is set, try to find the vision extension file. */
+ if($moduleExtPaths['vision']) $this->extActionFile = $moduleExtPaths['vision'] . $this->methodName . '.php';
+ if(file_exists($this->extActionFile)) return true;;
+
+ /* 4. 在喧喧目录中查找扩展文件。Then try to find the xuan extension file. */
+ if($moduleExtPaths['xuan']) $this->extActionFile = $moduleExtPaths['xuan'] . $this->methodName . '.php';
+ if(file_exists($this->extActionFile)) return true;;
+
+ /* 5. 最后尝试寻找公共扩展文件。Finally, try to find the common extension file. */
$this->extActionFile = $moduleExtPaths['common'] . $this->methodName . '.php';
+ if(empty($moduleExtPaths['common'])) return false;
return file_exists($this->extActionFile);
}
@@ -1482,8 +1572,10 @@ class baseRouter
if(empty($extFiles) and empty($hookFiles) and empty($apiFiles)) return $mainModelFile;
/* 计算合并之后的modelFile路径。Compute the merged model file path. */
- $extModelPrefix = ($siteExtended and !empty($this->siteCode)) ? $this->siteCode[0] . DS . $this->siteCode : '';
- $mergedModelDir = $this->getTmpRoot() . 'model' . DS . ($extModelPrefix ? $extModelPrefix . DS : '');
+ $extModelPrefix = $this->config->edition . DS . $this->config->vision . DS;
+ if($siteExtended and !empty($this->siteCode)) $extModelPrefix .= $this->siteCode[0] . DS . $this->siteCode;
+
+ $mergedModelDir = $this->getTmpRoot() . 'model' . DS . $extModelPrefix;
$mergedModelFile = $mergedModelDir . $moduleName . '.php';
if(!is_dir($mergedModelDir)) mkdir($mergedModelDir, 0755, true);
@@ -1554,9 +1646,7 @@ class baseRouter
/* 开始拼装代码。Prepare the codes. */
$modelLines = "getBasePath());\n";
- $modelLines .= "helper::import('" . str_replace($this->getBasePath(), '', $mainModelFile) . "');\n";
- $modelLines .= "helper::cd();\n";
+ $modelLines .= "helper::import(\$app->getBasePath() . '" . str_replace($this->getBasePath(), '', $this->getModulePath($this->appName, $moduleName)) . "model.php');\n";
$modelLines .= "class $tmpModelClass extends $modelClass \n{\n";
/* 将扩展文件的代码合并到代码中。Cycle all the extension files and merge them into model lines. */
@@ -1840,7 +1930,17 @@ class baseRouter
* 引入该模块的control文件。
* Include the control file of the module.
**/
- $file2Included = $this->setActionExtFile() ? $this->extActionFile : $this->controlFile;
+ $isExt = $this->setActionExtFile();
+ if($isExt)
+ {
+ $controlFile = $this->controlFile;
+ spl_autoload_register(function($class) use ($moduleName, $controlFile)
+ {
+ if($class == $moduleName) include $controlFile;
+ });
+ }
+
+ $file2Included = $isExt ? $this->extActionFile : $this->controlFile;
chdir(dirname($file2Included));
helper::import($file2Included);
@@ -2200,7 +2300,12 @@ class baseRouter
/* 查找扩展配置文件。Get extension config files. */
if($config->framework->extensionLevel > 0) $extConfigPath = $this->getModuleExtPath($appName, $moduleName, 'config');
- if($config->framework->extensionLevel >= 1 and !empty($extConfigPath['common'])) $commonExtConfigFiles = helper::ls($extConfigPath['common'], '.php');
+ if($config->framework->extensionLevel >= 1)
+ {
+ if(!empty($extConfigPath['common'])) $commonExtConfigFiles = helper::ls($extConfigPath['common'], '.php');
+ if(!empty($extConfigPath['vision'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['vision'], '.php'));
+ if(!empty($extConfigPath['custom'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['custom'], '.php'));
+ }
if($config->framework->extensionLevel == 2 and !empty($extConfigPath['site'])) $siteExtConfigFiles = helper::ls($extConfigPath['site'], '.php');
$extConfigFiles = array_merge($commonExtConfigFiles, $siteExtConfigFiles);
@@ -2315,7 +2420,12 @@ class baseRouter
$siteExtLangFiles = array();
$extLangPath = $this->getModuleExtPath($appName, $moduleName, 'lang');
- if($this->config->framework->extensionLevel >= 1 and !empty($extLangPath['common'])) $commonExtLangFiles = helper::ls($extLangPath['common'] . $this->clientLang, '.php');
+ if($this->config->framework->extensionLevel >= 1)
+ {
+ if(!empty($extLangPath['common'])) $commonExtLangFiles = helper::ls($extLangPath['common'] . $this->clientLang, '.php');
+ if(!empty($extLangPath['vision'])) $commonExtLangFiles = array_merge($commonExtLangFiles, helper::ls($extLangPath['vision'] . $this->clientLang, '.php'));
+ if(!empty($extLangPath['custom'])) $commonExtLangFiles = array_merge($commonExtLangFiles, helper::ls($extLangPath['custom'] . $this->clientLang, '.php'));
+ }
if($this->config->framework->extensionLevel == 2 and !empty($extLangPath['site'])) $siteExtLangFiles = helper::ls($extLangPath['site'] . $this->clientLang, '.php');
$extLangFiles = array_merge($commonExtLangFiles, $siteExtLangFiles);
}
diff --git a/framework/control.class.php b/framework/control.class.php
index 06beb03f0c..e71b8967d3 100644
--- a/framework/control.class.php
+++ b/framework/control.class.php
@@ -173,18 +173,43 @@ class control extends baseControl
if(!empty($viewExtPath))
{
$commonExtViewFile = $viewExtPath['common'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
+ $visionExtViewFile = $viewExtPath['vision'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
+ $customExtViewFile = $viewExtPath['custom'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
$siteExtViewFile = empty($viewExtPath['site']) ? '' : $viewExtPath['site'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
- $viewFile = file_exists($commonExtViewFile) ? $commonExtViewFile : $mainViewFile;
- $viewFile = (!empty($siteExtViewFile) and file_exists($siteExtViewFile)) ? $siteExtViewFile : $viewFile;
- if(!is_file($viewFile))
+ /* Get ext files, site > custom > vision > common. */
+ if(!empty($siteExtViewFile) and file_exists($siteExtViewFile))
{
- die(js::error($this->lang->notPage) . js::locate('back'));
+ $viewFile = $siteExtViewFile;
+ }
+ else if(file_exists($customExtViewFile))
+ {
+ $viewFile = $customExtViewFile;
+ }
+ else if(!empty($viewExtPath['vision']) and file_exists($visionExtViewFile))
+ {
+ $viewFile = $visionExtViewFile;
+ }
+ else if(file_exists($commonExtViewFile))
+ {
+ $viewFile = $commonExtViewFile;
}
- $commonExtHookFiles = glob($viewExtPath['common'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
- $siteExtHookFiles = empty($viewExtPath['site']) ? '' : glob($viewExtPath['site'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
- $extHookFiles = array_merge((array) $commonExtHookFiles, (array) $siteExtHookFiles);
+ if(!is_file($viewFile)) die(js::error($this->lang->notPage) . js::locate('back'));
+
+ /* Get ext hook files. */
+ if(empty($viewExtPath['vision']))
+ {
+ $commonExtHookFiles = glob($viewExtPath['common'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
+ }
+ else
+ {
+ $commonExtHookFiles = glob($viewExtPath['vision'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
+ }
+ $customExtHookFiles = glob($viewExtPath['custom'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
+
+ $siteExtHookFiles = empty($viewExtPath['site']) ? '' : glob($viewExtPath['site'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
+ $extHookFiles = array_merge((array)$commonExtHookFiles, (array)$customExtHookFiles, (array)$siteExtHookFiles);
}
if(!empty($extHookFiles)) return array('viewFile' => $viewFile, 'hookFiles' => $extHookFiles);
diff --git a/framework/helper.class.php b/framework/helper.class.php
index 91d903476a..ddc4aecb30 100644
--- a/framework/helper.class.php
+++ b/framework/helper.class.php
@@ -255,7 +255,7 @@ class helper extends baseHelper
* @param string $content
* @return void
*/
- public static function end($content)
+ public static function end($content = '')
{
throw EndResponseException::create($content);
}
diff --git a/framework/router.class.php b/framework/router.class.php
index 8c1df580f3..aa3316bec9 100755
--- a/framework/router.class.php
+++ b/framework/router.class.php
@@ -139,6 +139,9 @@ class router extends baseRouter
*/
public function setCommonLang()
{
+ if(defined('COMMONLANGSETTED')) return true;
+ define('COMMONLANGSETTED', true);
+
if(!defined('ITERATION_KEY')) define('ITERATION_KEY', 0);
if(!defined('SPRINT_KEY')) define('SPRINT_KEY', 1);
if(!defined('PRODUCT_KEY')) define('PRODUCT_KEY', 0);
@@ -301,6 +304,7 @@ class router extends baseRouter
/* 初始化数组。Init the variables. */
$extConfigFiles = array();
$commonExtConfigFiles = array();
+ $visionExtConfigFiles = array();
$siteExtConfigFiles = array();
/* 先获得模块的主配置文件。Get the main config file for current module first. */
@@ -308,7 +312,12 @@ class router extends baseRouter
/* 查找扩展配置文件。Get extension config files. */
if($config->framework->extensionLevel > 0) $extConfigPath = $this->getModuleExtPath($appName, $moduleName, 'config');
- if($config->framework->extensionLevel >= 1 and !empty($extConfigPath['common'])) $commonExtConfigFiles = helper::ls($extConfigPath['common'], '.php');
+ if($config->framework->extensionLevel >= 1)
+ {
+ if(!empty($extConfigPath['common'])) $commonExtConfigFiles = helper::ls($extConfigPath['common'], '.php');
+ if(!empty($extConfigPath['vision'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['vision'], '.php'));
+ if(!empty($extConfigPath['custom'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['custom'], '.php'));
+ }
if($config->framework->extensionLevel == 2 and !empty($extConfigPath['site'])) $siteExtConfigFiles = helper::ls($extConfigPath['site'], '.php');
$extConfigFiles = array_merge($commonExtConfigFiles, $siteExtConfigFiles);
@@ -429,7 +438,7 @@ class router extends baseRouter
}
else
{
- $action = $this->dbh->query("SELECT * FROM " . TABLE_WORKFLOWACTION . " WHERE `module` = '$this->moduleName' AND `action` = '$this->methodName'")->fetch();
+ $action = $this->dbh->query("SELECT * FROM " . TABLE_WORKFLOWACTION . " WHERE `module` = '$this->moduleName' AND `action` = '$this->methodName' AND `vision` = '{$this->config->vision}'")->fetch();
if(zget($action, 'extensionType') == 'override')
{
$this->rawModule = $this->moduleName;
diff --git a/module/action/model.php b/module/action/model.php
index f379663975..49718b947e 100755
--- a/module/action/model.php
+++ b/module/action/model.php
@@ -48,6 +48,7 @@ class actionModel extends model
$action->action = $actionType;
$action->date = helper::now();
$action->extra = $extra;
+ $action->vision = $this->config->vision;
if($objectType == 'story' and strpos(',reviewpassed,reviewrejected,reviewclarified,', ",$actionType,") !== false) $action->actor = $this->lang->action->system;
@@ -527,7 +528,7 @@ class actionModel extends model
$this->app->loadLang('execution');
$linkedProducts = $this->dao->select('id,name')->from(TABLE_PRODUCT)->where('id')->in($action->extra)->fetchPairs('id', 'name');
$action->extra = '';
- if($linkedProducts)
+ if($linkedProducts and $this->config->vision == 'rnd')
{
foreach($linkedProducts as $productID => $productName) $linkedProducts[$productID] = html::a(helper::createLink('product', 'browse', "productID=$productID"), "#{$productID} {$productName}");
$action->extra = sprintf($this->lang->execution->action->extra, '' . join(', ', $linkedProducts) . '');
@@ -617,6 +618,7 @@ class actionModel extends model
$trashes = $this->dao->select('*')->from(TABLE_ACTION)
->where('action')->eq('deleted')
->andWhere('extra')->eq($extra)
+ ->andWhere('vision')->eq($this->config->vision)
->orderBy($orderBy)->page($pager)->fetchAll();
if(!$trashes) return array();
@@ -873,6 +875,7 @@ class actionModel extends model
/* Get actions. */
$actions = $this->dao->select('*')->from(TABLE_ACTION)
->where('objectType')->notIN('kanbanregion,kanbanlane,kanbancolumn')
+ ->andWhere('vision')->eq($this->config->vision)
->beginIF($period != 'all')->andWhere('date')->gt($begin)->fi()
->beginIF($period != 'all')->andWhere('date')->lt($end)->fi()
->beginIF($date)->andWhere('date' . ($direction == 'next' ? '<' : '>') . "'{$date}'")->fi()
@@ -885,6 +888,8 @@ class actionModel extends model
->beginIF(!empty($executions))->andWhere('execution')->in(array_keys($executions))->fi()
->beginIF(is_numeric($executionID))->andWhere('execution')->eq($executionID)->fi()
->markRight(1)
+ /* Types excluded from Lite. */
+ ->beginIF($this->config->vision == 'lite')->andWhere('objectType')->notin('product')->fi()
->beginIF($productID == 'notzero')->andWhere('product')->gt(0)->andWhere('product')->notlike('%,0,%')->fi()
->beginIF($projectID == 'notzero')->andWhere('project')->gt(0)->fi()
->beginIF($executionID == 'notzero')->andWhere('execution')->gt(0)->fi()
@@ -1355,6 +1360,11 @@ class actionModel extends model
$action->objectLink = helper::createLink('assetlib', 'storyView', "storyID=$action->objectID");
}
+ if($action->objectType == 'story' and $this->config->vision == 'lite')
+ {
+ $action->objectLink = helper::createLink('projectstory', 'view', "storyID=$action->objectID");
+ }
+
if(strpos(',kanbanregion,kanbancard,', ",{$action->objectType},") !== false)
{
$table = $this->config->objectTables[$action->objectType];
diff --git a/module/backup/control.php b/module/backup/control.php
index 62144de15a..40f081973d 100644
--- a/module/backup/control.php
+++ b/module/backup/control.php
@@ -98,7 +98,7 @@ class backup extends control
if($reload == 'yes')
{
echo js::alert(sprintf($this->lang->backup->error->noWritable, $this->backupPath));
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
else
{
@@ -117,7 +117,7 @@ class backup extends control
if($reload == 'yes')
{
echo js::alert(sprintf($this->lang->backup->error->backupFile, $result->error));
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
else
{
@@ -133,7 +133,7 @@ class backup extends control
if($reload == 'yes')
{
echo js::alert(sprintf($this->lang->backup->error->backupCode, $result->error));
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
else
{
@@ -164,7 +164,7 @@ class backup extends control
}
}
- if($reload == 'yes') die(js::reload('parent'));
+ if($reload == 'yes') return print(js::reload('parent'));
echo $this->lang->backup->success->backup . "\n";
}
@@ -245,7 +245,7 @@ class backup extends control
rename($this->backupPath . $fileName . '.code.zip.php', $this->backupPath . $fileName . '.code.zip');
}
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
/**
@@ -258,26 +258,26 @@ class backup extends control
*/
public function delete($fileName, $confirm = 'no')
{
- if($confirm == 'no') die(js::confirm($this->lang->backup->confirmDelete, inlink('delete', "fileName=$fileName&confirm=yes")));
+ if($confirm == 'no') return print(js::confirm($this->lang->backup->confirmDelete, inlink('delete', "fileName=$fileName&confirm=yes")));
/* Delete database file. */
if(file_exists($this->backupPath . $fileName . '.sql.php') and !unlink($this->backupPath . $fileName . '.sql.php'))
{
- die(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.sql.php')));
+ return print(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.sql.php')));
}
if(file_exists($this->backupPath . $fileName . '.sql') and !unlink($this->backupPath . $fileName . '.sql'))
{
- die(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.sql')));
+ return print(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.sql')));
}
/* Delete attatchments file. */
if(file_exists($this->backupPath . $fileName . '.file.zip.php') and !unlink($this->backupPath . $fileName . '.file.zip.php'))
{
- die(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.file.zip.php')));
+ return print(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.file.zip.php')));
}
if(file_exists($this->backupPath . $fileName . '.file.zip') and !unlink($this->backupPath . $fileName . '.file.zip'))
{
- die(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.file.zip')));
+ return print(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.file.zip')));
}
if(file_exists($this->backupPath . $fileName . '.file'))
{
@@ -289,11 +289,11 @@ class backup extends control
/* Delete code file. */
if(file_exists($this->backupPath . $fileName . '.code.zip.php') and !unlink($this->backupPath . $fileName . '.code.zip.php'))
{
- die(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.code.zip.php')));
+ return print(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.code.zip.php')));
}
if(file_exists($this->backupPath . $fileName . '.code.zip') and !unlink($this->backupPath . $fileName . '.code.zip'))
{
- die(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.code.zip')));
+ return print(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.code.zip')));
}
if(file_exists($this->backupPath . $fileName . '.code'))
{
@@ -302,7 +302,7 @@ class backup extends control
$this->backup->processSummary($this->backupPath . $fileName . '.code', 0, 0, array(), 0, 'delete');
}
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
/**
@@ -317,7 +317,7 @@ class backup extends control
{
$data = fixer::input('post')->get();
$this->loadModel('setting')->setItem('system.backup.holdDays', $data->holdDays);
- die(js::reload('parent.parent'));
+ return print(js::reload('parent.parent'));
}
$this->display();
@@ -337,7 +337,7 @@ class backup extends control
{
$this->app->loadLang('extension');
$this->view->error = sprintf($this->lang->extension->noticeOkFile, str_replace(dirname($this->app->getBasePath()) . DS, '', $statusFile));
- die($this->display());
+ return print($this->display());
}
if(strtolower($this->server->request_method) == "post")
@@ -355,14 +355,14 @@ class backup extends control
if($settingDir)
{
$settingDir = rtrim($settingDir, DS) . DS;
- if(!is_dir($settingDir) and mkdir($settingDir, 0777, true)) die(js::alert($this->lang->backup->error->noCreateDir));
- if(!is_writable($settingDir)) die(js::alert(strip_tags(sprintf($this->lang->backup->error->noWritable, $settingDir))));
+ if(!is_dir($settingDir) and mkdir($settingDir, 0777, true)) return print(js::alert($this->lang->backup->error->noCreateDir));
+ if(!is_writable($settingDir)) return print(js::alert(strip_tags(sprintf($this->lang->backup->error->noWritable, $settingDir))));
if($data->settingDir == $this->app->getTmpRoot() . 'backup' . DS) $settingDir = '';
}
$this->setting->setItem('system.backup.settingDir', $settingDir);
- die(js::reload('parent.parent'));
+ return print(js::reload('parent.parent'));
}
$this->display();
}
@@ -406,6 +406,6 @@ class backup extends control
$message = sprintf($this->lang->backup->progressCode, zget($log, 'allCount', 0), zget($log, 'count', 0));
}
- die($message);
+ return print($message);
}
}
diff --git a/module/block/control.php b/module/block/control.php
index 79dbbbd85c..d3f7eafb2d 100644
--- a/module/block/control.php
+++ b/module/block/control.php
@@ -22,7 +22,7 @@ class block extends control
parent::__construct($moduleName, $methodName);
/* Mark the call from zentao or ranzhi. */
$this->selfCall = !isset($_GET['hash']);
- if($this->methodName != 'admin' and $this->methodName != 'dashboard' and !$this->selfCall and !$this->loadModel('sso')->checkKey()) die('');
+ if($this->methodName != 'admin' and $this->methodName != 'dashboard' and !$this->selfCall and !$this->loadModel('sso')->checkKey()) helper::end('');
}
/**
@@ -103,8 +103,8 @@ class block extends control
{
$source = isset($this->lang->block->moduleList[$source]) ? $source : '';
$this->block->save($id, $source, $type, $this->session->blockModule);
- if(dao::isError()) die(js::error(dao::geterror()));
- die(js::reload('parent'));
+ if(dao::isError()) return print(js::error(dao::geterror()));
+ return print(js::reload('parent'));
}
$block = $this->block->getByID($id);
@@ -226,6 +226,7 @@ class block extends control
{
if($this->loadModel('user')->isLogon()) $this->session->set('blockModule', $module);
$blocks = $this->block->getBlockList($module, $type);
+ $vision = $this->config->vision;
$commonField = 'common';
if($module == 'project' and $projectID)
@@ -234,12 +235,17 @@ class block extends control
$commonField = $project->model . 'common';
}
- $inited = empty($this->config->$module->$commonField->blockInited) ? '' : $this->config->$module->$commonField->blockInited;
+ $inited = $this->dao->select('*')->from(TABLE_CONFIG)
+ ->where('module')->eq($module)
+ ->andWhere('owner')->eq($this->app->user->account)
+ ->andWhere('`key`')->eq('blockInited')
+ ->andWhere('vision')->eq($vision)
+ ->fetch('value');
/* Init block when vist index first. */
if((empty($blocks) and !$inited and !defined('TUTORIAL')))
{
- if($this->block->initBlock($module, $type)) die(js::reload());
+ if($this->block->initBlock($module, $type)) return print(js::reload());
}
$acls = $this->app->user->rights['acls'];
@@ -274,6 +280,10 @@ class block extends control
{
$block->moreLink = $this->createLink('project', 'dynamic', "projectID=$projectID&type=all");
}
+ elseif($moduleName == 'project' and $method == 'execution')
+ {
+ $block->moreLink = $this->createLink('project', 'execution', "status=all&projectID=$projectID");
+ }
elseif($moduleName == 'project' and $method == 'testtask')
{
$block->moreLink = $this->createLink('project', 'testtask', "projectID=$projectID");
@@ -303,7 +313,7 @@ class block extends control
$this->view->shortBlocks = $shortBlocks;
$this->view->module = $module;
- if($this->app->getViewType() == 'json') die(json_encode($blocks));
+ if($this->app->getViewType() == 'json') return print(json_encode($blocks));
$this->display();
}
@@ -445,7 +455,7 @@ class block extends control
$this->app->loadLang('common');
$this->app->loadLang('block');
- if(!$this->block->checkAPI($this->get->hash)) die();
+ if(!$this->block->checkAPI($this->get->hash)) return;
}
$mode = strtolower($this->get->mode);
@@ -557,7 +567,7 @@ class block extends control
$output['status'] = is_object($this->view) ? 'success' : 'fail';
$output['data'] = json_encode($this->view);
$output['md5'] = md5(json_encode($this->view));
- die(json_encode($output));
+ return print(json_encode($output));
}
$this->display();
@@ -619,7 +629,7 @@ class block extends control
public function printTaskBlock()
{
$this->session->set('taskList', $this->app->getURI(true), 'execution');
- if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
+ if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
$account = $this->app->user->account;
$type = $this->params->type;
@@ -637,7 +647,7 @@ class block extends control
public function printBugBlock()
{
$this->session->set('bugList', $this->app->getURI(true), 'qa');
- if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
+ if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
$projectID = $this->lang->navGroup->qa == 'project' ? $this->session->project : 0;
$projectID = $this->view->block->module == 'my' ? 0 : $projectID;
@@ -700,7 +710,7 @@ class block extends control
$this->session->set('productList', $this->app->getURI(true), 'product');
$this->session->set('testtaskList', $this->app->getURI(true), 'qa');
$this->session->set('buildList', $this->app->getURI(true), 'execution');
- if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
+ if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
$this->view->testtasks = $this->dao->select('distinct t1.*,t2.name as productName,t3.name as buildName,t4.name as projectName')->from(TABLE_TESTTASK)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product=t2.id')
@@ -726,7 +736,7 @@ class block extends control
public function printStoryBlock()
{
$this->session->set('storyList', $this->app->getURI(true), 'product');
- if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
+ if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
$this->app->loadClass('pager', $static = true);
$count = isset($this->params->count) ? (int)$this->params->count : 0;
@@ -830,7 +840,7 @@ class block extends control
public function printProductBlock()
{
$this->app->loadClass('pager', $static = true);
- if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
+ if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
$count = isset($this->params->count) ? (int)$this->params->count : 0;
$type = isset($this->params->type) ? $this->params->type : '';
$pager = pager::init(0, $count , 1);
@@ -871,7 +881,7 @@ class block extends control
*/
public function printProjectStatisticBlock()
{
- if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
+ if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
/* Load models and langs. */
$this->loadModel('project');
@@ -946,7 +956,7 @@ class block extends control
*/
public function printProductStatisticBlock($storyType = 'story')
{
- if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
+ if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
$status = isset($this->params->type) ? $this->params->type : '';
$count = isset($this->params->count) ? $this->params->count : '';
@@ -1045,7 +1055,7 @@ class block extends control
*/
public function printExecutionStatisticBlock()
{
- if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
+ if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
$this->app->loadLang('task');
$this->app->loadLang('story');
@@ -1228,7 +1238,7 @@ class block extends control
{
$uri = $this->app->getURI(true);
$this->session->set('issueList', $uri, 'project');
- if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
+ if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->issues = $this->loadModel('issue')->getBlockIssues($this->session->project, $this->params->type, $this->viewType == 'json' ? 0 : (int)$this->params->count, $this->params->orderBy);
}
@@ -1337,7 +1347,7 @@ class block extends control
*/
public function printScrumListBlock()
{
- if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
+ if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
$count = isset($this->params->count) ? (int)$this->params->count : 15;
$type = isset($this->params->type) ? $this->params->type : 'undone';
@@ -1386,7 +1396,8 @@ class block extends control
{
$sprints = $this->dao->select('status, count(*) as sprints')->from(TABLE_EXECUTION)
->where('deleted')->eq(0)
- ->andWhere('type')->eq('sprint')
+ ->beginIF($this->config->vision == 'lite')->andWhere('type')->eq('kanban')->fi()
+ ->beginIF($this->config->vision == 'rnd')->andWhere('type')->eq('sprint')->fi()
->andWhere('parent')->eq($this->session->project)
->groupBy('status')
->fetchPairs();
@@ -1495,7 +1506,7 @@ class block extends control
*/
public function printQaStatisticBlock()
{
- if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
+ if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
$this->app->loadLang('bug');
$status = isset($this->params->type) ? $this->params->type : '';
@@ -1670,7 +1681,7 @@ class block extends control
public function printExecutionBlock()
{
$this->app->loadClass('pager', $static = true);
- if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) die();
+ if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
$count = isset($this->params->count) ? (int)$this->params->count : 0;
$status = isset($this->params->type) ? $this->params->type : 'all';
$pager = pager::init(0, $count, 1);
@@ -1691,6 +1702,7 @@ class block extends control
*/
public function printAssignToMeBlock($longBlock = true)
{
+ $hasViewPriv = array();
if(common::hasPriv('todo', 'view')) $hasViewPriv['todo'] = true;
if(common::hasPriv('task', 'view')) $hasViewPriv['task'] = true;
if(common::hasPriv('bug', 'view')) $hasViewPriv['bug'] = true;
@@ -1855,7 +1867,7 @@ class block extends control
$closedBlock = isset($this->config->block->closed) ? $this->config->block->closed : '';
$this->dao->delete()->from(TABLE_BLOCK)->where('source')->eq($block->source)->andWhere('block')->eq($block->block)->exec();
$this->loadModel('setting')->setItem('system.block.closed', $closedBlock . ",{$block->source}|{$block->block}");
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
/**
@@ -1868,11 +1880,21 @@ class block extends control
*/
public function ajaxReset($module, $confirm = 'no')
{
- if($confirm != 'yes') die(js::confirm($this->lang->block->confirmReset, inlink('ajaxReset', "module=$module&confirm=yes")));
+ if($confirm != 'yes') return print(js::confirm($this->lang->block->confirmReset, inlink('ajaxReset', "module=$module&confirm=yes")));
- $this->dao->delete()->from(TABLE_BLOCK)->where('module')->eq($module)->andWhere('account')->eq($this->app->user->account)->exec();
- $this->dao->delete()->from(TABLE_CONFIG)->where('module')->eq($module)->andWhere('owner')->eq($this->app->user->account)->andWhere('`key`')->eq('blockInited')->exec();
- die(js::reload('parent'));
+ $this->dao->delete()->from(TABLE_BLOCK)
+ ->where('module')->eq($module)
+ ->andWhere('vision')->eq($this->config->vision)
+ ->andWhere('account')->eq($this->app->user->account)
+ ->exec();
+
+ $this->dao->delete()->from(TABLE_CONFIG)
+ ->where('module')->eq($module)
+ ->andWhere('vision')->eq($this->config->vision)
+ ->andWhere('owner')->eq($this->app->user->account)
+ ->andWhere('`key`')->eq('blockInited')
+ ->exec();
+ return print(js::reload('parent'));
}
/**
@@ -1889,7 +1911,7 @@ class block extends control
{
$this->dao->delete()->from(TABLE_BLOCK)->where('module')->eq($module)->andWhere('account')->eq($this->app->user->account)->exec();
$this->dao->delete()->from(TABLE_CONFIG)->where('module')->eq($module)->andWhere('owner')->eq($this->app->user->account)->andWhere('`key`')->eq('blockInited')->exec();
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
elseif($confirm == 'no')
{
diff --git a/module/block/lang/en.php b/module/block/lang/en.php
index b0a9a555e3..566c2e53a1 100644
--- a/module/block/lang/en.php
+++ b/module/block/lang/en.php
@@ -99,6 +99,7 @@ $lang->block->productName = $lang->productCommon . ' Name';
$lang->block->totalStory = 'The Total ' . $lang->SRCommon;
$lang->block->totalBug = 'The Total Bug';
$lang->block->totalRelease = 'Release The Number';
+$lang->block->totalTask = 'The Total ' . $lang->task->common;
$lang->block->totalInvestment = 'Total investment';
$lang->block->totalPeople = 'Total number';
diff --git a/module/block/lang/zh-cn.php b/module/block/lang/zh-cn.php
index e5d8deface..dfdf15e786 100644
--- a/module/block/lang/zh-cn.php
+++ b/module/block/lang/zh-cn.php
@@ -99,6 +99,7 @@ $lang->block->productName = $lang->productCommon . '名称';
$lang->block->totalStory = '总' . $lang->SRCommon;
$lang->block->totalBug = '总Bug';
$lang->block->totalRelease = '发布次数';
+$lang->block->totalTask = '总' . $lang->task->common;
$lang->block->totalInvestment = '总投入';
$lang->block->totalPeople = '总人数';
@@ -106,6 +107,24 @@ $lang->block->spent = '已花费';
$lang->block->budget = '预算';
$lang->block->left = '剩余';
+$lang->block->titleList['flowchart'] = '流程图';
+$lang->block->titleList['statistic'] = '项目统计';
+$lang->block->titleList['recentproject'] = '我近期参与的项目';
+$lang->block->titleList['assigntome'] = '待处理';
+$lang->block->titleList['projectteam'] = '项目人力投入';
+$lang->block->titleList['project'] = '项目列表';
+$lang->block->titleList['dynamic'] = '最新动态';
+$lang->block->titleList['list'] = '我的待办';
+$lang->block->titleList['contribute'] = '我的贡献';
+$lang->block->titleList['scrumoverview'] = '项目概况';
+$lang->block->titleList['scrumtest'] = '待测版本';
+$lang->block->titleList['scrumlist'] = '迭代列表';
+$lang->block->titleList['sprint'] = '迭代总览';
+$lang->block->titleList['projectdynamic'] = '最新动态';
+$lang->block->titleList['bug'] = '指派给我的Bug';
+$lang->block->titleList['case'] = '指派给我的用例';
+$lang->block->titleList['testtask'] = '待测版本列表';
+
$lang->block->default['waterfall']['project']['3']['title'] = "项目计划";
$lang->block->default['waterfall']['project']['3']['block'] = 'waterfallgantt';
$lang->block->default['waterfall']['project']['3']['source'] = 'project';
@@ -143,6 +162,7 @@ $lang->block->default['scrum']['project']['4']['grid'] = 4;
$lang->block->default['scrum']['project']['5']['title'] = '最新动态';
$lang->block->default['scrum']['project']['5']['block'] = 'projectdynamic';
$lang->block->default['scrum']['project']['5']['grid'] = 4;
+$lang->block->default['kanban'] = $lang->block->default['scrum'];
$lang->block->default['product']['1']['title'] = $lang->productCommon . '统计';
$lang->block->default['product']['1']['block'] = 'statistic';
diff --git a/module/block/model.php b/module/block/model.php
index 510fcb22d9..2a581efa4e 100644
--- a/module/block/model.php
+++ b/module/block/model.php
@@ -133,6 +133,7 @@ class blockModel extends model
{
$blocks = $this->dao->select('*')->from(TABLE_BLOCK)->where('account')->eq($this->app->user->account)
->andWhere('module')->eq($module)
+ ->andWhere('vision')->eq($this->config->vision)
->andWhere('hidden')->eq(0)
->beginIF($type)->andWhere('type')->eq($type)->fi()
->orderBy('`order`')
@@ -231,19 +232,21 @@ class blockModel extends model
{
$flow = isset($this->config->global->flow) ? $this->config->global->flow : 'full';
$account = $this->app->user->account;
+ $vision = $this->config->vision;
+
if($module == 'project')
{
$blocks = $this->lang->block->default[$type]['project'];
/* Mark project block has init. */
- $this->loadModel('setting')->setItem("$account.$module.{$type}common.blockInited", true);
+ $this->loadModel('setting')->setItem("$account.$module.{$type}common.blockInited@$vision", true);
}
else
{
$blocks = $module == 'my' ? $this->lang->block->default[$flow][$module] : $this->lang->block->default[$module];
/* Mark this app has init. */
- $this->loadModel('setting')->setItem("$account.$module.common.blockInited", true);
+ $this->loadModel('setting')->setItem("$account.$module.common.blockInited@$vision", true);
}
$this->loadModel('setting')->setItem("$account.$module.block.initVersion", $this->config->block->version);
@@ -254,11 +257,11 @@ class blockModel extends model
$block['type'] = $type;
$block['account'] = $account;
$block['params'] = isset($block['params']) ? helper::jsonEncode($block['params']) : '';
+ $block['vision'] = $this->config->vision;
if(!isset($block['source'])) $block['source'] = $module;
$this->dao->replace(TABLE_BLOCK)->data($block)->exec();
}
-
return !dao::isError();
}
@@ -457,6 +460,7 @@ class blockModel extends model
public function getProjectParams()
{
$this->app->loadLang('project');
+ $params = new stdclass();
$params->type['name'] = $this->lang->block->type;
$params->type['options'] = $this->lang->project->featureBar;
$params->type['control'] = 'select';
@@ -477,6 +481,7 @@ class blockModel extends model
public function getProjectTeamParams()
{
$this->app->loadLang('project');
+ $params = new stdclass();
$params->type['name'] = $this->lang->block->type;
$params->type['options'] = $this->lang->project->featureBar;
$params->type['control'] = 'select';
@@ -507,6 +512,7 @@ class blockModel extends model
*/
public function getProductParams()
{
+ $params = new stdclass();
$params->type['name'] = $this->lang->block->type;
$params->type['options'] = $this->lang->block->typeList->product;
$params->type['control'] = 'select';
@@ -715,6 +721,7 @@ class blockModel extends model
*/
public function getExecutionParams()
{
+ $params = new stdclass();
$params->type['name'] = $this->lang->block->type;
$params->type['options'] = $this->lang->block->typeList->execution;
$params->type['control'] = 'select';
@@ -730,6 +737,7 @@ class blockModel extends model
*/
public function getAssignToMeParams()
{
+ $params = new stdclass();
$params->todoCount['name'] = $this->lang->block->todoCount;
$params->todoCount['default'] = 20;
$params->todoCount['control'] = 'input';
diff --git a/module/block/view/scrumoverviewblock.html.php b/module/block/view/scrumoverviewblock.html.php
index fcf990cc03..cf05b83451 100644
--- a/module/block/view/scrumoverviewblock.html.php
+++ b/module/block/view/scrumoverviewblock.html.php
@@ -10,6 +10,7 @@
* @link http://www.zentao.net
*/
?>
+config->vision;?>
" . $lang->project->create, '', "class='btn btn-primary'")?>
@@ -22,7 +23,11 @@
|
workingHour;?> |
|
+
+ block->taskCount;?> |
+
block->bugCount;?> |
+
|
@@ -34,8 +39,8 @@
teamCount ? html::a($this->createLink('project', 'team', 'projectID=' . $projectID), $totalData[$projectID]->teamCount) : 0;?> |
block->estimatedHours . ':';?> |
estimate . $lang->execution->workHour;?> |
- block->totalBug. ':';?> |
- allBugs;?> |
+ block->totalTask : $lang->block->totalBug) . ':';?> |
+ allTasks : $totalData[$projectID]->allBugs;?> |
| block->done . ':';?> |
@@ -44,8 +49,8 @@
|
block->consumedHours . ':';?> |
consumed . $lang->execution->workHour;?> |
- bug->statusList['resolved'] . ':';?> |
- doneBugs;?> |
+ block->done : $lang->bug->statusList['resolved']) . ':';?> |
+ doneTasks : $totalData[$projectID]->doneBugs;?> |
| block->left . ':';?> |
@@ -54,8 +59,8 @@
|
|
|
- bug->unResolved . ':';?> |
- leftBugs;?> |
+ block->undone : $lang->bug->unResolved) . ':';?> |
+ leftTasks : $totalData[$projectID]->leftBugs;?> |
diff --git a/module/branch/control.php b/module/branch/control.php
index 25a6266d33..f6c04f8425 100644
--- a/module/branch/control.php
+++ b/module/branch/control.php
@@ -62,10 +62,10 @@ class branch extends control
if($_POST)
{
$branchID = $this->branch->create($productID);
- if(dao::isError()) die(js::error(dao::getError()));
+ if(dao::isError()) return print(js::error(dao::getError()));
$this->loadModel('action')->create('branch', $branchID, 'Opened');
- die(js::reload('parent.parent'));
+ return print(js::reload('parent.parent'));
}
$this->view->product = $this->loadModel('product')->getById($productID);
@@ -84,10 +84,10 @@ class branch extends control
if($_POST)
{
$changes = $this->branch->update($branchID);
- if(dao::isError()) die(js::error(dao::getError()));
+ if(dao::isError()) return print(js::error(dao::getError()));
if($changes) $this->loadModel('action')->create('branch', $branchID, 'Edited');
- die(js::reload('parent.parent'));
+ return print(js::reload('parent.parent'));
}
$this->view->product = $this->loadModel('product')->getById($productID);
@@ -116,12 +116,12 @@ class branch extends control
if($change) $this->action->create('branch', $branchID, 'Edited', '', $extra);
}
- die(js::locate($this->session->branchManage, 'parent'));
+ return print(js::locate($this->session->branchManage, 'parent'));
}
$branchList = $this->branch->getList($productID, 0, 'all');
$branchIDList = $this->post->branchIDList;
- if(empty($branchIDList)) die(js::locate($this->session->branchManage, 'parent'));
+ if(empty($branchIDList)) return print(js::locate($this->session->branchManage, 'parent'));
foreach($branchList as $branch)
{
@@ -148,14 +148,14 @@ class branch extends control
if($confirm == 'no')
{
- die(js::confirm(str_replace('@branch@', $this->lang->product->branchName[$productType], $this->lang->branch->confirmClose), inlink('close', "branchID=$branchID&confirm=yes")));
+ return print(js::confirm(str_replace('@branch@', $this->lang->product->branchName[$productType], $this->lang->branch->confirmClose), inlink('close', "branchID=$branchID&confirm=yes")));
}
$this->branch->close($branchID);
- if(dao::isError()) die(js::error(dao::getError()));
+ if(dao::isError()) return print(js::error(dao::getError()));
$this->loadModel('action')->create('branch', $branchID, 'Closed');
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
/**
@@ -173,14 +173,14 @@ class branch extends control
if($confirm == 'no')
{
- die(js::confirm(str_replace('@branch@', $this->lang->product->branchName[$productType], $this->lang->branch->confirmActivate), inlink('activate', "branchID=$branchID&confirm=yes")));
+ return print(js::confirm(str_replace('@branch@', $this->lang->product->branchName[$productType], $this->lang->branch->confirmActivate), inlink('activate', "branchID=$branchID&confirm=yes")));
}
$this->branch->activate($branchID);
- if(dao::isError()) die(js::error(dao::getError()));
+ if(dao::isError()) return print(js::error(dao::getError()));
$this->loadModel('action')->create('branch', $branchID, 'Activated');
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
/**
@@ -236,14 +236,14 @@ class branch extends control
{
$this->app->loadLang('product');
$productType = $this->branch->getProductType($branchID);
- if(!$this->branch->checkBranchData($branchID)) die(js::alert(str_replace('@branch@', $this->lang->product->branchName[$productType], $this->lang->branch->canNotDelete)));
+ if(!$this->branch->checkBranchData($branchID)) return print(js::alert(str_replace('@branch@', $this->lang->product->branchName[$productType], $this->lang->branch->canNotDelete)));
if($confirm == 'no')
{
- die(js::confirm(str_replace('@branch@', $this->lang->product->branchName[$productType], $this->lang->branch->confirmDelete), inlink('delete', "branchID=$branchID&confirm=yes")));
+ return print(js::confirm(str_replace('@branch@', $this->lang->product->branchName[$productType], $this->lang->branch->confirmDelete), inlink('delete', "branchID=$branchID&confirm=yes")));
}
$this->branch->delete(TABLE_BRANCH, $branchID);
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
/**
@@ -260,7 +260,7 @@ class branch extends control
{
$param = $param ? $param : 'all';
$product = $this->loadModel('product')->getById($productID);
- if(empty($product) or $product->type == 'normal') die();
+ if(empty($product) or $product->type == 'normal') return;
$branches = $this->loadModel('branch')->getList($productID, $projectID, $param);
$branchOption = array();
@@ -270,7 +270,7 @@ class branch extends control
$branchOption[$branchInfo->id] = $branchInfo->name;
$branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : '');
}
- die(html::select('branch', strpos($param, 'active') !== false ? $branchOption : $branchTagOption, $oldBranch, "class='form-control' onchange='loadBranch(this)'"));
+ return print(html::select('branch', strpos($param, 'active') !== false ? $branchOption : $branchTagOption, $oldBranch, "class='form-control' onchange='loadBranch(this)'"));
}
/**
@@ -288,14 +288,14 @@ class branch extends control
{
$this->app->loadLang('product');
$productType = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch('type');
- die(js::confirm(str_replace('@branch@', $this->lang->product->branchName[$productType], $this->lang->branch->confirmSetDefault), inlink('setDefault', "productID=$productID&branchID=$branchID&confirm=yes")));
+ return print(js::confirm(str_replace('@branch@', $this->lang->product->branchName[$productType], $this->lang->branch->confirmSetDefault), inlink('setDefault', "productID=$productID&branchID=$branchID&confirm=yes")));
}
$this->branch->setDefault($productID, $branchID);
$this->loadModel('action')->create('branch', $branchID, 'SetDefaultBranch', '', $productID);
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
/**
diff --git a/module/branch/model.php b/module/branch/model.php
index d32b12b34a..01dff6d983 100644
--- a/module/branch/model.php
+++ b/module/branch/model.php
@@ -271,7 +271,7 @@ class branchModel extends model
->where('id')->eq($branchID)
->exec();
- if(dao::isError()) die(js::error('branch#' . $branchID . dao::getError(true)));
+ if(dao::isError()) return print(js::error('branch#' . $branchID . dao::getError(true)));
$changes[$branchID] = common::createChanges($oldBranchList[$branchID], $branch);
}
@@ -331,7 +331,7 @@ class branchModel extends model
{
foreach($data->branch as $branchID => $branch)
{
- if(!$branch) die(js::alert($this->lang->branch->nameNotEmpty));
+ if(!$branch) return print(js::alert($this->lang->branch->nameNotEmpty));
if($oldBranches[$branchID] != $branch) $this->dao->update(TABLE_BRANCH)->set('name')->eq($branch)->where('id')->eq($branchID)->exec();
}
}
diff --git a/module/bug/config.php b/module/bug/config.php
index df5a1739bf..3a561f048d 100644
--- a/module/bug/config.php
+++ b/module/bug/config.php
@@ -105,6 +105,7 @@ $config->bug->search['fields']['resolvedDate'] = $lang->bug->resolvedDate;
$config->bug->search['fields']['closedDate'] = $lang->bug->closedDate;
$config->bug->search['fields']['lastEditedDate'] = $lang->bug->lastEditedDateAB;
$config->bug->search['fields']['deadline'] = $lang->bug->deadline;
+$config->bug->search['fields']['activatedDate'] = $lang->bug->activatedDate;
$config->bug->search['params']['title'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
$config->bug->search['params']['keywords'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
@@ -149,6 +150,7 @@ $config->bug->search['params']['resolvedDate'] = array('operator' => '=',
$config->bug->search['params']['closedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['lastEditedDate']= array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['deadline'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+$config->bug->search['params']['activatedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->datatable = new stdclass();
$config->bug->datatable->defaultField = array('id', 'severity', 'pri', 'confirmed', 'title', 'status', 'openedBy', 'openedDate', 'assignedTo', 'resolution', 'actions');
diff --git a/module/bug/control.php b/module/bug/control.php
index 421c991ae1..29c7483a65 100644
--- a/module/bug/control.php
+++ b/module/bug/control.php
@@ -999,7 +999,7 @@ class bug extends control
$this->view->branchTagOption = $branchTagOption;
$this->view->tasks = $this->task->getExecutionTaskPairs($bug->execution);
$this->view->testtasks = $this->loadModel('testtask')->getPairs($bug->product, $bug->execution, $bug->testtask);
- $this->view->users = $this->user->getPairs('noclosed', "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy,$bug->openedBy");
+ $this->view->users = $this->user->getPairs('', "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy,$bug->openedBy");
$this->view->openedBuilds = $openedBuilds;
$this->view->resolvedBuilds = array('' => '') + $openedBuilds + $oldResolvedBuild;
$this->view->actions = $this->action->getList('bug', $bugID);
@@ -1135,7 +1135,7 @@ class bug extends control
$appendUsers[$bug->assignedTo] = $bug->assignedTo;
$appendUsers[$bug->resolvedBy] = $bug->resolvedBy;
}
- $users = $this->user->getPairs('devfirst|noclosed', $appendUsers, $this->config->maxCount);
+ $users = $this->user->getPairs('devfirst', $appendUsers, $this->config->maxCount);
$users = array('' => '', 'ditto' => $this->lang->bug->ditto) + $users;
/* Assign. */
@@ -1448,7 +1448,7 @@ class bug extends control
if(!empty($_POST))
{
$changes = $this->bug->resolve($bugID, $extra);
- if(dao::isError()) die(js::error(dao::getError()));
+ if(dao::isError()) return print(js::error(dao::getError()));
$files = $this->loadModel('file')->saveUpload('bug', $bugID);
$fileAction = !empty($files) ? $this->lang->addFiles . join(',', $files) . "\n" : '';
@@ -1468,7 +1468,7 @@ class bug extends control
$confirmURL = $this->createLink('task', 'view', "taskID=$bug->toTask");
unset($_GET['onlybody']);
$cancelURL = $this->createLink('bug', 'view', "bugID=$bugID");
- die(js::confirm(sprintf($this->lang->bug->remindTask, $bug->toTask), $confirmURL, $cancelURL, 'parent', 'parent.parent'));
+ return print(js::confirm(sprintf($this->lang->bug->remindTask, $bug->toTask), $confirmURL, $cancelURL, 'parent', 'parent.parent'));
}
}
@@ -1530,11 +1530,11 @@ class bug extends control
*/
public function batchResolve($resolution, $resolvedBuild = '')
{
- $bugIDList = $this->post->bugIDList ? $this->post->bugIDList : die(js::locate($this->session->bugList, 'parent'));
- $bugIDList = array_unique($bugIDList);
+ if(!$this->post->bugIDList) return print(js::locate($this->session->bugList, 'parent'));
+ $bugIDList = array_unique($this->post->bugIDList);
$changes = $this->bug->batchResolve($bugIDList, $resolution, $resolvedBuild);
- if(dao::isError()) die(js::error(dao::getError()));
+ if(dao::isError()) return print(js::error(dao::getError()));
foreach($changes as $bugID => $bugChanges)
{
@@ -1543,7 +1543,7 @@ class bug extends control
}
$this->loadModel('score')->create('ajax', 'batchOther');
- die(js::locate($this->session->bugList, 'parent'));
+ return print(js::locate($this->session->bugList, 'parent'));
}
/**
@@ -1560,7 +1560,7 @@ class bug extends control
if(!empty($_POST))
{
$changes = $this->bug->activate($bugID, $extra);
- if(dao::isError()) die(js::error(dao::getError()));
+ if(dao::isError()) return print(js::error(dao::getError()));
$files = $this->loadModel('file')->saveUpload('bug', $bugID);
@@ -1587,7 +1587,7 @@ class bug extends control
return print(js::closeModal('parent.parent'));
}
}
- die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
+ return print(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
}
$productID = $bug->product;
@@ -1620,7 +1620,7 @@ class bug extends control
if(!empty($_POST))
{
$changes = $this->bug->close($bugID, $extra);
- if(dao::isError()) die(js::error(dao::getError()));
+ if(dao::isError()) return print(js::error(dao::getError()));
$actionID = $this->action->create('bug', $bugID, 'Closed', $this->post->comment);
$this->action->logHistory($actionID, $changes);
@@ -1709,8 +1709,8 @@ class bug extends control
$this->view->pager = $pager;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->recTotal = $recTotal;
- $this->view->recPerPage = $recPerPage;
- $this->view->pageID = $pageID;
+ $this->view->recPerPage = $recPerPage;
+ $this->view->pageID = $pageID;
$this->display();
}
@@ -1747,7 +1747,7 @@ class bug extends control
$this->loadModel('score')->create('ajax', 'batchOther');
if(isset($skipBugs)) echo js::alert(sprintf($this->lang->bug->skipClose, join(',', $skipBugs)));
}
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
/**
@@ -1763,11 +1763,12 @@ class bug extends control
$activateBugs = $this->bug->batchActivate();
foreach($activateBugs as $bugID => $bug) $this->action->create('bug', $bugID, 'Activated', $bug['comment']);
$this->loadModel('score')->create('ajax', 'batchOther');
- die(js::locate($this->session->bugList, 'parent'));
+ return print(js::locate($this->session->bugList, 'parent'));
}
- $bugIDList = $this->post->bugIDList ? $this->post->bugIDList : die(js::locate($this->session->bugList, 'parent'));
- $bugIDList = array_unique($bugIDList);
+ if(!$this->post->bugIDList) return print(js::locate($this->session->bugList, 'parent'));
+
+ $bugIDList = array_unique($this->post->bugIDList);
$bugs = $this->dao->select('id, title, status, resolvedBy, openedBuild')->from(TABLE_BUG)->where('id')->in($bugIDList)->fetchAll('id');
$this->qa->setMenu($this->products, $productID, $branch);
@@ -1796,7 +1797,7 @@ class bug extends control
$this->bug->checkBugExecutionPriv($bug);
$this->dao->update(TABLE_BUG)->set('storyVersion')->eq($bug->latestStoryVersion)->where('id')->eq($bugID)->exec();
$this->loadModel('action')->create('bug', $bugID, 'confirmed', '', $bug->latestStoryVersion);
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
/**
@@ -1812,7 +1813,7 @@ class bug extends control
$bug = $this->bug->getById($bugID);
if($confirm == 'no')
{
- die(js::confirm($this->lang->bug->confirmDelete, inlink('delete', "bugID=$bugID&confirm=yes")));
+ return print(js::confirm($this->lang->bug->confirmDelete, inlink('delete', "bugID=$bugID&confirm=yes")));
}
else
{
@@ -1825,7 +1826,7 @@ class bug extends control
$confirmURL = $this->createLink('task', 'view', "taskID=$bug->toTask");
unset($_GET['onlybody']);
$cancelURL = $this->createLink('bug', 'view', "bugID=$bugID");
- die(js::confirm(sprintf($this->lang->bug->remindTask, $bug->toTask), $confirmURL, $cancelURL, 'parent', 'parent.parent'));
+ return print(js::confirm(sprintf($this->lang->bug->remindTask, $bug->toTask), $confirmURL, $cancelURL, 'parent', 'parent.parent'));
}
}
@@ -1834,7 +1835,7 @@ class bug extends control
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess));
$locateLink = $this->session->bugList ? $this->session->bugList : inlink('browse', "productID={$bug->product}");
- die(js::locate($locateLink, 'parent'));
+ return print(js::locate($locateLink, 'parent'));
}
}
@@ -1853,8 +1854,8 @@ class bug extends control
$account = $user->account;
$bugs = $this->bug->getUserBugPairs($account);
- if($id) die(html::select("bugs[$id]", $bugs, '', 'class="form-control"'));
- die(html::select('bug', $bugs, '', 'class=form-control'));
+ if($id) return print(html::select("bugs[$id]", $bugs, '', 'class="form-control"'));
+ return print(html::select('bug', $bugs, '', 'class=form-control'));
}
/**
@@ -1876,7 +1877,7 @@ class bug extends control
if(!empty($this->config->isINT)) $firstLetter = '';
$realName = $firstLetter . ($user->realname ? $user->realname : $account);
}
- die(json_encode(array($account, $realName)));
+ return print(json_encode(array($account, $realName)));
}
/**
@@ -1891,7 +1892,7 @@ class bug extends control
{
$executionMembers = $this->user->getTeamMemberPairs($executionID, 'execution', '', $selectedUser);
- die(html::select('assignedTo', $executionMembers, $selectedUser, 'class="form-control"'));
+ return print(html::select('assignedTo', $executionMembers, $selectedUser, 'class="form-control"'));
}
/**
@@ -1906,7 +1907,7 @@ class bug extends control
{
$productMembers = $this->bug->getProductMemberPairs($productID);
- die(html::select('assignedTo', $productMembers, $selectedUser, 'class="form-control"'));
+ return print(html::select('assignedTo', $productMembers, $selectedUser, 'class="form-control"'));
}
/**
@@ -1920,7 +1921,7 @@ class bug extends control
{
$allUsers = $this->loadModel('user')->getPairs('devfirst|noclosed');
- die(html::select('assignedTo', $allUsers, $selectedUser, 'class="form-control"'));
+ return print(html::select('assignedTo', $allUsers, $selectedUser, 'class="form-control"'));
}
/**
@@ -2152,7 +2153,7 @@ class bug extends control
$bug = $this->dao->select('*')->from(TABLE_BUG)->where('id')->eq($bugID)->fetch();
$realname = $this->dao->select('*')->from(TABLE_USER)->where('account')->eq($bug->assignedTo)->fetch('realname');
$bug->assignedTo = $realname ? $realname : ($bug->assignedTo == 'closed' ? 'Closed' : $bug->assignedTo);
- die(json_encode($bug));
+ return print(json_encode($bug));
}
/**
@@ -2171,7 +2172,7 @@ class bug extends control
$pri = $this->lang->bug->priList;
$severity = $this->lang->bug->severityList;
- die(json_encode(array('modules' => $modules, 'categories' => $type, 'versions' => $builds, 'severities' => $severity, 'priorities' => $pri)));
+ return print(json_encode(array('modules' => $modules, 'categories' => $type, 'versions' => $builds, 'severities' => $severity, 'priorities' => $pri)));
}
/**
@@ -2213,7 +2214,7 @@ class bug extends control
$users = $this->loadModel('user')->getPairs('noclosed');
$teamMembers = empty($projectID) ? array() : $this->loadModel('project')->getTeamMemberPairs($projectID);
foreach($teamMembers as $account => $member) $teamMembers[$account] = $users[$account];
- die(html::select('assignedTo', $teamMembers, '', 'class="form-control"'));
+ return print(html::select('assignedTo', $teamMembers, '', 'class="form-control"'));
}
diff --git a/module/bug/model.php b/module/bug/model.php
index 65a8a45bcb..22254220c0 100644
--- a/module/bug/model.php
+++ b/module/bug/model.php
@@ -217,7 +217,7 @@ class bugModel extends model
$bug->{$extendField->field} = htmlSpecialString($bug->{$extendField->field});
$message = $this->checkFlowRule($extendField, $bug->{$extendField->field});
- if($message) die(js::alert($message));
+ if($message) return print(js::alert($message));
}
/* Required field check. */
@@ -226,7 +226,7 @@ class bugModel extends model
$field = trim($field);
if($field and empty($bug->$field))
{
- die(js::alert(sprintf($this->lang->error->notempty, $this->lang->bug->$field)));
+ return print(js::alert(sprintf($this->lang->error->notempty, $this->lang->bug->$field)));
}
}
@@ -266,7 +266,7 @@ class bugModel extends model
->autoCheck()
->batchCheck($this->config->bug->create->requiredFields, 'notempty')
->exec();
- if(dao::isError()) die(js::error(dao::getError()));
+ if(dao::isError()) return print(js::error(dao::getError()));
$bugID = $this->dao->lastInsertID();
@@ -290,7 +290,7 @@ class bugModel extends model
unset($file);
}
- if(dao::isError()) die(js::error('bug#' . ($i+1) . dao::getError(true)));
+ if(dao::isError()) return print(js::error('bug#' . ($i+1) . dao::getError(true)));
$actions[$bugID] = $this->action->create('bug', $bugID, 'Opened');
}
@@ -430,8 +430,8 @@ class bugModel extends model
{
echo(js::alert($this->lang->bug->executionAccessDenied));
$loginLink = $this->config->requestType == 'GET' ? "?{$this->config->moduleVar}=user&{$this->config->methodVar}=login" : "user{$this->config->requestFix}login";
- if(strpos($this->server->http_referer, $loginLink) !== false) die(js::locate(helper::createLink('bug', 'index', '')));
- die(js::locate('back'));
+ if(strpos($this->server->http_referer, $loginLink) !== false) return print(js::locate(helper::createLink('bug', 'index', '')));
+ return print(js::locate('back'));
}
}
@@ -804,7 +804,7 @@ class bugModel extends model
$bug->{$extendField->field} = htmlSpecialString($bug->{$extendField->field});
$message = $this->checkFlowRule($extendField, $bug->{$extendField->field});
- if($message) die(js::alert($message));
+ if($message) return print(js::alert($message));
}
$bugs[$bugID] = $bug;
@@ -834,7 +834,7 @@ class bugModel extends model
}
else
{
- die(js::error('bug#' . $bugID . dao::getError(true)));
+ return print(js::error('bug#' . $bugID . dao::getError(true)));
}
}
}
@@ -887,7 +887,7 @@ class bugModel extends model
{
$oldBug = $bugs[$bugID];
$this->dao->update(TABLE_BUG)->data($bug, $skipFields = 'comment')->autoCheck()->where('id')->eq((int)$bugID)->exec();
- if(dao::isError()) die(js::error('bug#' . $bugID . dao::getError(true)));
+ if(dao::isError()) return print(js::error('bug#' . $bugID . dao::getError(true)));
$this->dao->update(TABLE_BUG)->set('activatedCount = activatedCount + 1')->where('id')->eq((int)$bugID)->exec();
}
@@ -1357,15 +1357,16 @@ class bugModel extends model
* @param int $bugID
* @param string $browseType
* @param int $queryID
+ * @param object $pager
* @access public
* @return array
*/
- public function getBugs2Link($bugID, $browseType = 'bySearch', $queryID = 0, $pager)
+ public function getBugs2Link($bugID, $browseType = 'bySearch', $queryID = 0, $pager = null)
{
if($browseType == 'bySearch')
{
$bug = $this->getById($bugID);
- $bugIDList = $bug->id . ',' . $bug->linkBug;
+ $bugIDList = $bug->id . ',' . $bug->linkBug;
$bugs2Link = $this->getBySearch($bug->product, 'all', $queryID, 'id', $bugIDList, $pager);
return $bugs2Link;
}
diff --git a/module/build/control.php b/module/build/control.php
index 7d4ebf4b1e..b4ec04530f 100644
--- a/module/build/control.php
+++ b/module/build/control.php
@@ -217,7 +217,7 @@ class build extends control
if(!$build)
{
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'fail', 'code' => 404, 'message' => '404 Not found'));
- die(js::error($this->lang->notFound) . js::locate($this->createLink('execution', 'all')));
+ return print(js::error($this->lang->notFound) . js::locate($this->createLink('execution', 'all')));
}
$this->session->project = $build->project;
@@ -306,7 +306,7 @@ class build extends control
{
if($confirm == 'no')
{
- die(js::confirm($this->lang->build->confirmDelete, $this->createLink('build', 'delete', "buildID=$buildID&confirm=yes")));
+ return print(js::confirm($this->lang->build->confirmDelete, $this->createLink('build', 'delete', "buildID=$buildID&confirm=yes")));
}
else
{
@@ -333,7 +333,7 @@ class build extends control
$link = $this->app->tab == 'project' ? $this->createLink('project', 'build', "projectID=$build->project") : $this->createLink('execution', 'build', "executionID=$build->execution");
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success'));
- die(js::locate($link, 'parent'));
+ return print(js::locate($link, 'parent'));
}
}
@@ -356,21 +356,21 @@ class build extends control
{
$params = ($type == 'all') ? 'noempty,withbranch' : 'noempty, noterminate, nodone, withbranch';
$builds = $this->build->getBuildPairs($productID, $branch, $params);
- if($isJsonView) die(json_encode($builds));
- else die(html::select($varName . '[]', $builds, $build, 'size=4 class=form-control multiple'));
+ if($isJsonView) return print(json_encode($builds));
+ return print(html::select($varName . '[]', $builds, $build, 'size=4 class=form-control multiple'));
}
if($varName == 'openedBuilds' )
{
$builds = $this->build->getBuildPairs($productID, $branch, 'noempty');
- if($isJsonView) die(json_encode($builds));
- else die(html::select($varName . "[$index][]", $builds, $build, 'size=4 class=form-control multiple'));
+ if($isJsonView) return print(json_encode($builds));
+ return print(html::select($varName . "[$index][]", $builds, $build, 'size=4 class=form-control multiple'));
}
if($varName == 'resolvedBuild')
{
$params = ($type == 'all') ? 'withbranch' : 'noterminate, nodone, withbranch';
$builds = $this->build->getBuildPairs($productID, $branch, $params);
- if($isJsonView) die(json_encode($builds));
- else die(html::select($varName, $builds, $build, "class='form-control'"));
+ if($isJsonView) return print(json_encode($builds));
+ return print(html::select($varName, $builds, $build, "class='form-control'"));
}
}
@@ -396,8 +396,8 @@ class build extends control
$params = ($type == 'all') ? 'noempty, withbranch' : 'noempty, noterminate, nodone, withbranch';
$builds = $this->build->getBuildPairs($productID, $branch, $params, $projectID, 'project', $build);
- if($isJsonView) die(json_encode($builds));
- die(html::select($varName . '[]', $builds , '', 'size=4 class=form-control multiple'));
+ if($isJsonView) return print(json_encode($builds));
+ return print(html::select($varName . '[]', $builds , '', 'size=4 class=form-control multiple'));
}
if($varName == 'resolvedBuild')
{
@@ -405,8 +405,8 @@ class build extends control
$params = ($type == 'all') ? 'withbranch' : 'noterminate, nodone, withbranch';
$builds = $this->build->getBuildPairs($productID, $branch, $params, $projectID, 'project', $build);
- if($isJsonView) die(json_encode($builds));
- die(html::select($varName, $builds, $build, "class='form-control'"));
+ if($isJsonView) return print(json_encode($builds));
+ return print(html::select($varName, $builds, $build, "class='form-control'"));
}
}
@@ -432,16 +432,16 @@ class build extends control
$params = ($type == 'all') ? 'noempty' : 'noempty, noterminate, nodone';
$builds = $this->build->getBuildPairs($productID, $branch, $params, $executionID, 'execution', $build);
- if($isJsonView) die(json_encode($builds));
- else die(html::select($varName . '[]', $builds , '', 'size=4 class=form-control multiple'));
+ if($isJsonView) return print(json_encode($builds));
+ return print(html::select($varName . '[]', $builds , '', 'size=4 class=form-control multiple'));
}
if($varName == 'openedBuilds')
{
if(empty($executionID)) $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $index, $type);
$builds = $this->build->getBuildPairs($productID, $branch, 'noempty', $executionID, 'execution');
- if($isJsonView) die(json_encode($builds));
- else die(html::select($varName . "[$index][]", $builds , $build, 'size=4 class=form-control multiple'));
+ if($isJsonView) return print(json_encode($builds));
+ return print(html::select($varName . "[$index][]", $builds , $build, 'size=4 class=form-control multiple'));
}
if($varName == 'resolvedBuild')
{
@@ -449,13 +449,13 @@ class build extends control
$params = ($type == 'all') ? '' : 'noterminate, nodone';
$builds = $this->build->getBuildPairs($productID, $branch, $params, $executionID, 'execution', $build);
- if($isJsonView) die(json_encode($builds));
- else die(html::select($varName, $builds, $build, "class='form-control'"));
+ if($isJsonView) return print(json_encode($builds));
+ return print(html::select($varName, $builds, $build, "class='form-control'"));
}
if($varName == 'testTaskBuild')
{
$builds = $this->build->getBuildPairs($productID, $branch, 'noempty,notrunk', $executionID, 'execution');
- if($isJsonView) die(json_encode($builds));
+ if($isJsonView) return print(json_encode($builds));
if(empty($builds))
{
@@ -464,20 +464,20 @@ class build extends control
$html = html::a($this->createLink('build', 'create', "executionID=$executionID&productID=$productID&projectID=$projectID", '', $onlybody = true), $this->lang->build->create, '', "data-toggle='modal' data-type='iframe'");
$html .= ' ';
$html .= html::a("javascript:loadExecutionBuilds($executionID)", $this->lang->refresh);
- die($html);
+ return print($html);
}
- die(html::select('build', array('') + $builds, $build, "class='form-control'"));
+ return print(html::select('build', array('') + $builds, $build, "class='form-control'"));
}
if($varName == 'dropdownList')
{
$builds = $this->build->getBuildPairs($productID, $branch, 'noempty,notrunk', $executionID, 'execution');
- if($isJsonView) die(json_encode($builds));
+ if($isJsonView) return print(json_encode($builds));
$list = "";
foreach($builds as $buildID => $buildName) $list .= html::a(inlink('view', "buildID={$buildID}"), $buildName);
$list .= '
';
- die($list);
+ return print($list);
}
}
@@ -498,7 +498,7 @@ class build extends control
if(!empty($_POST['stories']))
{
$this->build->linkStory($buildID);
- die(js::locate(inlink('view', "buildID=$buildID&type=story"), 'parent'));
+ return print(js::locate(inlink('view', "buildID=$buildID&type=story"), 'parent'));
}
$this->session->set('storyList', inlink('view', "buildID=$buildID&type=story&link=true¶m=" . helper::safe64Encode("&browseType=$browseType&queryID=$param")), $this->app->tab);
@@ -588,7 +588,7 @@ class build extends control
}
return $this->send($response);
}
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
/**
@@ -601,7 +601,7 @@ class build extends control
public function batchUnlinkStory($buildID)
{
$this->build->batchUnlinkStory($buildID);
- die(js::locate($this->createLink('build', 'view', "buildID=$buildID&type=story"), 'parent'));
+ return print(js::locate($this->createLink('build', 'view', "buildID=$buildID&type=story"), 'parent'));
}
/**
@@ -621,7 +621,7 @@ class build extends control
if(!empty($_POST['bugs']))
{
$this->build->linkBug($buildID);
- die(js::locate(inlink('view', "buildID=$buildID&type=bug"), 'parent'));
+ return print(js::locate(inlink('view', "buildID=$buildID&type=bug"), 'parent'));
}
$this->session->set('bugList', inlink('view', "buildID=$buildID&type=bug&link=true¶m=" . helper::safe64Encode("&browseType=$browseType&queryID=$param")), 'qa');
@@ -711,7 +711,7 @@ class build extends control
}
return $this->send($response);
}
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
/**
@@ -724,6 +724,6 @@ class build extends control
public function batchUnlinkBug($buildID)
{
$this->build->batchUnlinkBug($buildID);
- die(js::locate($this->createLink('build', 'view', "buildID=$buildID&type=bug"), 'parent'));
+ return print(js::locate($this->createLink('build', 'view', "buildID=$buildID&type=bug"), 'parent'));
}
}
diff --git a/module/caselib/control.php b/module/caselib/control.php
index 8aae891edf..586b756ccb 100644
--- a/module/caselib/control.php
+++ b/module/caselib/control.php
@@ -124,7 +124,7 @@ class caselib extends control
{
if($confirm == 'no')
{
- die(js::confirm($this->lang->caselib->libraryDelete, inlink('delete', "libID=$libID&confirm=yes")));
+ return print(js::confirm($this->lang->caselib->libraryDelete, inlink('delete', "libID=$libID&confirm=yes")));
}
else
{
@@ -147,7 +147,7 @@ class caselib extends control
}
return $this->send($response);
}
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
}
@@ -252,20 +252,20 @@ class caselib extends control
$this->config->testcase->create->requiredFields = $this->config->caselib->createcase->requiredFields;
setcookie('lastLibCaseModule', (int)$this->post->module, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, false);
$caseResult = $this->testcase->create($bugID = 0);
- if(!$caseResult or dao::isError()) die(js::error(dao::getError()));
+ if(!$caseResult or dao::isError()) return print(js::error(dao::getError()));
$caseID = $caseResult['id'];
if($caseResult['status'] == 'exists')
{
echo js::alert(sprintf($this->lang->duplicate, $this->lang->testcase->common));
- die(js::locate($this->createLink('testcase', 'view', "caseID=$caseID"), 'parent'));
+ return print(js::locate($this->createLink('testcase', 'view', "caseID=$caseID"), 'parent'));
}
$this->loadModel('action')->create('case', $caseID, 'Opened');
/* If link from no head then reload. */
- if(isonlybody()) die(js::reload('parent'));
- die(js::locate($this->createLink('caselib', 'browse', "libID={$libID}&browseType=byModule¶m={$_POST['module']}"), 'parent'));
+ if(isonlybody()) return print(js::reload('parent'));
+ return print(js::locate($this->createLink('caselib', 'browse', "libID={$libID}&browseType=byModule¶m={$_POST['module']}"), 'parent'));
}
/* Set lib menu. */
$libraries = $this->caselib->getLibraries();
@@ -340,9 +340,9 @@ class caselib extends control
if(!empty($_POST))
{
$caseID = $this->caselib->batchCreateCase($libID);
- if(dao::isError()) die(js::error(dao::getError()));
- if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
- die(js::locate($this->createLink('caselib', 'browse', "libID=$libID&browseType=byModule¶m=$moduleID"), 'parent'));
+ if(dao::isError()) return print(js::error(dao::getError()));
+ if(isonlybody()) return print(js::closeModal('parent.parent', 'this'));
+ return print(js::locate($this->createLink('caselib', 'browse', "libID=$libID&browseType=byModule¶m=$moduleID"), 'parent'));
}
$libraries = $this->caselib->getLibraries();
@@ -378,7 +378,7 @@ class caselib extends control
{
$libID = (int)$libID;
$lib = $this->caselib->getById($libID, true);
- if(!isset($lib->id)) die(js::error($this->lang->notFound) . js::locate($this->createLink('qa', 'index')));
+ if(!isset($lib->id)) return print(js::error($this->lang->notFound) . js::locate($this->createLink('qa', 'index')));
/* Set lib menu. */
$libraries = $this->caselib->getLibraries();
@@ -555,12 +555,12 @@ class caselib extends control
if(!isset($fields[$title])) continue;
$columnKey[] = $fields[$title];
}
- if(count($columnKey) != count($header)) die(js::alert($this->lang->testcase->errorEncode));
+ if(count($columnKey) != count($header)) return print(js::alert($this->lang->testcase->errorEncode));
}
$this->session->set('fileImport', $fileName);
- die(js::locate(inlink('showImport', "libID=$libID"), 'parent.parent'));
+ return print(js::locate(inlink('showImport', "libID=$libID"), 'parent.parent'));
}
$this->display();
}
@@ -589,11 +589,11 @@ class caselib extends control
if($this->post->isEndPage)
{
unlink($tmpFile);
- die(js::locate(inlink('browse', "libID=$libID"), 'parent'));
+ return print(js::locate(inlink('browse', "libID=$libID"), 'parent'));
}
else
{
- die(js::locate(inlink('showImport', "libID=$libID&pagerID=" . ($this->post->pagerID + 1) . "&maxImport=$maxImport&insert=" . zget($_POST, 'insert', '')), 'parent'));
+ return print(js::locate(inlink('showImport', "libID=$libID&pagerID=" . ($this->post->pagerID + 1) . "&maxImport=$maxImport&insert=" . zget($_POST, 'insert', '')), 'parent'));
}
}
@@ -759,7 +759,7 @@ class caselib extends control
unlink($this->session->fileImport);
unset($_SESSION['fileImport']);
echo js::alert($this->lang->error->noData);
- die(js::locate($this->createLink('caselib', 'browse', "libID=$libID")));
+ return print(js::locate($this->createLink('caselib', 'browse', "libID=$libID")));
}
$allCount = count($caseData);
@@ -771,13 +771,13 @@ class caselib extends control
$this->view->allCount = $allCount;
$this->view->maxImport = $maxImport;
$this->view->libID = $libID;
- die($this->display());
+ return print($this->display());
}
$allPager = ceil($allCount / $maxImport);
$caseData = array_slice($caseData, ($pagerID - 1) * $maxImport, $maxImport, true);
}
- if(empty($caseData)) die(js::locate(inlink('browse', "libID=$libID")));
+ if(empty($caseData)) return print(js::locate(inlink('browse', "libID=$libID")));
/* Judge whether the items is too large and set session. */
$countInputVars = count($caseData) * 9 + (isset($stepVars) ? $stepVars : 0);
diff --git a/module/caselib/model.php b/module/caselib/model.php
index 89ed3045e2..c7f3d043ba 100644
--- a/module/caselib/model.php
+++ b/module/caselib/model.php
@@ -389,7 +389,7 @@ class caselibModel extends model
$cases[$key] = $caseData;
$line++;
}
- if(dao::isError()) die(js::error(dao::getError()));
+ if(dao::isError()) return print(js::error(dao::getError()));
$forceNotReview = $this->testcase->forceNotReview();
foreach($cases as $key => $caseData)
@@ -537,7 +537,7 @@ class caselibModel extends model
foreach($cases->title as $i => $title)
{
- if(!empty($cases->title[$i]) and empty($cases->type[$i])) die(js::alert(sprintf($this->lang->error->notempty, $this->lang->testcase->type)));
+ if(!empty($cases->title[$i]) and empty($cases->type[$i])) return print(js::alert(sprintf($this->lang->error->notempty, $this->lang->testcase->type)));
}
$module = 0;
@@ -582,7 +582,7 @@ class caselibModel extends model
if(dao::isError())
{
echo js::error(dao::getError());
- die(js::reload('parent'));
+ return print(js::reload('parent'));
}
$caseID = $this->dao->lastInsertID();
diff --git a/module/common/lang/common.php b/module/common/lang/common.php
index 84ae09cae3..38d73ae72d 100644
--- a/module/common/lang/common.php
+++ b/module/common/lang/common.php
@@ -174,7 +174,6 @@ $lang->createIcons['program'] = 'program';
$lang->createIcons['kanbanspace'] = 'cube';
$lang->createIcons['kanban'] = 'kanban';
-
$lang->noMenuModule = array('report', 'my', 'todo', 'effort', 'program', 'product', 'execution', 'task', 'build', 'productplan', 'project', 'projectrelease', 'projectstory', 'story', 'branch', 'release', 'attend', 'leave', 'makeup', 'overtime', 'lieu', 'custom', 'admin', 'mail', 'extension', 'dev', 'backup', 'action', 'cron', 'pssp', 'sms', 'message', 'webhook', 'search', 'score', 'stage', 'entry', 'jenkins', 'gitlab');
if(isset($_SESSION['tutorialMode']) and $_SESSION['tutorialMode'] and !defined('TUTORIAL')) define('TUTORIAL', true);
diff --git a/module/common/lang/en.php b/module/common/lang/en.php
index 9849859a23..0cb5fe57dd 100644
--- a/module/common/lang/en.php
+++ b/module/common/lang/en.php
@@ -88,6 +88,7 @@ $lang->history = 'History';
$lang->attatch = 'Files';
$lang->reverse = 'Inverse';
$lang->switchDisplay = 'Toggle';
+$lang->switchTo = 'Switch To';
$lang->expand = 'Expand';
$lang->collapse = 'Collapse';
$lang->saveSuccess = 'Saved';
@@ -321,6 +322,10 @@ $lang->exportFileTypeList['html'] = 'html';
$lang->exportTypeList['all'] = 'All Data';
$lang->exportTypeList['selected'] = 'Selected Data';
+$lang->visionList = array();
+$lang->visionList['rnd'] = 'R&D';
+$lang->visionList['lite'] = 'Lite';
+
$lang->createObjects['todo'] = 'Todo';
$lang->createObjects['effort'] = 'Effort';
$lang->createObjects['bug'] = 'Bug';
diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php
index 0c99f1773e..bc0017d791 100644
--- a/module/common/lang/zh-cn.php
+++ b/module/common/lang/zh-cn.php
@@ -88,6 +88,7 @@ $lang->history = '历史记录';
$lang->attatch = '附件';
$lang->reverse = '切换顺序';
$lang->switchDisplay = '切换显示';
+$lang->switchTo = '切换到';
$lang->expand = '展开全部';
$lang->collapse = '收起';
$lang->saveSuccess = '保存成功';
@@ -321,6 +322,10 @@ $lang->exportFileTypeList['html'] = 'html';
$lang->exportTypeList['all'] = '全部记录';
$lang->exportTypeList['selected'] = '选中记录';
+$lang->visionList = array();
+$lang->visionList['rnd'] = '研发综合界面';
+$lang->visionList['lite'] = '迅捷界面';
+
$lang->createObjects['todo'] = '待办';
$lang->createObjects['effort'] = '日志';
$lang->createObjects['bug'] = 'Bug';
diff --git a/module/common/model.php b/module/common/model.php
index 4a70f7907c..60240e3547 100644
--- a/module/common/model.php
+++ b/module/common/model.php
@@ -31,7 +31,7 @@ class commonModel extends model
$this->loadConfigFromDB();
$this->app->setTimezone();
$this->loadCustomFromDB();
- if(!$this->checkIP()) die($this->lang->ipLimited);
+ if(!$this->checkIP()) return print($this->lang->ipLimited);
$this->app->loadLang('company');
}
}
@@ -259,7 +259,7 @@ class commonModel extends model
{
/* Get configs of system and current user. */
$account = isset($this->app->user->account) ? $this->app->user->account : '';
- if($this->config->db->name) $config = $this->loadModel('setting')->getSysAndPersonalConfig($account);
+ if($this->config->db->name) $config = $this->loadModel('setting')->getSysAndPersonalConfig($account);
$this->config->system = isset($config['system']) ? $config['system'] : array();
$this->config->personal = isset($config[$account]) ? $config[$account] : array();
@@ -359,7 +359,7 @@ class commonModel extends model
{
echo js::locate($denyLink);
}
- exit;
+ helper::end();
}
/**
@@ -393,9 +393,6 @@ class commonModel extends model
{
$isGuest = $app->user->account == 'guest';
- echo "";
- echo html::avatar($app->user);
- echo '';
echo "';
+
+ echo "";
+ echo html::avatar($app->user);
+ echo '';
+ }
+ }
+
+ /**
+ * Print vision switcher.
+ *
+ * @static
+ * @access public
+ * @return void
+ */
+ public static function printVisionSwitcher()
+ {
+ global $lang, $app;
+
+ if(isset($app->user))
+ {
+ $currentVision = $app->config->vision;
+ $userVisions = array_filter(explode(',', $app->user->visions));
+ if(count($userVisions) < 2)
+ {
+ echo "{$lang->visionList[$currentVision]}
";
+ return;
+ }
+
+ echo "';
+
+ echo "";
+ echo "{$lang->visionList[$currentVision]}
";
+ echo '';
}
}
@@ -467,9 +510,7 @@ class commonModel extends model
{
global $app, $config, $lang;
- $html = "";
- $html .= "";
- $html .= "