Merge branch 'sprint/168'

This commit is contained in:
孙广明
2021-11-30 14:38:32 +08:00
357 changed files with 14454 additions and 2349 deletions
+48 -39
View File
@@ -170,6 +170,7 @@ define('TABLE_USERTPL', '`' . $config->db->prefix . 'usertpl`');
define('TABLE_PRODUCT', '`' . $config->db->prefix . 'product`');
define('TABLE_BRANCH', '`' . $config->db->prefix . 'branch`');
define('TABLE_EXPECT', '`' . $config->db->prefix . 'expect`');
define('TABLE_STAGE', '`' . $config->db->prefix . 'stage`');
define('TABLE_STAKEHOLDER', '`' . $config->db->prefix . 'stakeholder`');
define('TABLE_STORY', '`' . $config->db->prefix . 'story`');
define('TABLE_STORYSPEC', '`' . $config->db->prefix . 'storyspec`');
@@ -195,6 +196,8 @@ define('TABLE_BURN', '`' . $config->db->prefix . 'burn`');
define('TABLE_BUILD', '`' . $config->db->prefix . 'build`');
define('TABLE_ACL', '`' . $config->db->prefix . 'acl`');
define('TABLE_DESIGN', '`' . $config->db->prefix . 'design`');
define('TABLE_DESIGNSPEC', '`' . $config->db->prefix . 'designspec`');
define('TABLE_DOCLIB', '`' . $config->db->prefix . 'doclib`');
define('TABLE_DOC', '`' . $config->db->prefix . 'doc`');
define('TABLE_API', '`' . $config->db->prefix . 'api`');
@@ -206,6 +209,7 @@ define('TABLE_API_LIB_RELEASE', '`' . $config->db->prefix . 'api_lib_release`');
define('TABLE_MODULE', '`' . $config->db->prefix . 'module`');
define('TABLE_ACTION', '`' . $config->db->prefix . 'action`');
define('TABLE_FILE', '`' . $config->db->prefix . 'file`');
define('TABLE_HOLIDAY', '`' . $config->db->prefix . 'holiday`');
define('TABLE_HISTORY', '`' . $config->db->prefix . 'history`');
define('TABLE_EXTENSION', '`' . $config->db->prefix . 'extension`');
define('TABLE_CRON', '`' . $config->db->prefix . 'cron`');
@@ -216,6 +220,7 @@ define('TABLE_SUITECASE', '`' . $config->db->prefix . 'suitecase`');
define('TABLE_TESTREPORT', '`' . $config->db->prefix . 'testreport`');
define('TABLE_ENTRY', '`' . $config->db->prefix . 'entry`');
define('TABLE_WEEKLYREPORT', '`' . $config->db->prefix . 'weeklyreport`');
define('TABLE_WEBHOOK', '`' . $config->db->prefix . 'webhook`');
define('TABLE_LOG', '`' . $config->db->prefix . 'log`');
define('TABLE_SCORE', '`' . $config->db->prefix . 'score`');
@@ -226,53 +231,57 @@ define('TABLE_JOB', '`' . $config->db->prefix . 'job`');
define('TABLE_COMPILE', '`' . $config->db->prefix . 'compile`');
define('TABLE_MR', '`' . $config->db->prefix . 'mr`');
define('TABLE_REPO', '`' . $config->db->prefix . 'repo`');
define('TABLE_RELATION', '`' . $config->db->prefix . 'relation`');
define('TABLE_REPOHISTORY', '`' . $config->db->prefix . 'repohistory`');
define('TABLE_REPOFILES', '`' . $config->db->prefix . 'repofiles`');
define('TABLE_REPOBRANCH', '`' . $config->db->prefix . 'repobranch`');
define('TABLE_REPO', '`' . $config->db->prefix . 'repo`');
define('TABLE_RELATION', '`' . $config->db->prefix . 'relation`');
define('TABLE_REPOHISTORY', '`' . $config->db->prefix . 'repohistory`');
define('TABLE_REPOFILES', '`' . $config->db->prefix . 'repofiles`');
define('TABLE_REPOBRANCH', '`' . $config->db->prefix . 'repobranch`');
define('TABLE_KANBANLANE', '`' . $config->db->prefix . 'kanbanlane`');
define('TABLE_KANBANCOLUMN', '`' . $config->db->prefix . 'kanbancolumn`');
if(!defined('TABLE_LANG')) define('TABLE_LANG', '`' . $config->db->prefix . 'lang`');
if(!defined('TABLE_PROJECTSPEC')) define('TABLE_PROJECTSPEC', '`' . $config->db->prefix . 'projectspec`');
if(!defined('TABLE_SEARCHINDEX')) define('TABLE_SEARCHINDEX', $config->db->prefix . 'searchindex');
if(!defined('TABLE_SEARCHDICT')) define('TABLE_SEARCHDICT', $config->db->prefix . 'searchdict');
$config->objectTables['product'] = TABLE_PRODUCT;
$config->objectTables['productplan'] = TABLE_PRODUCTPLAN;
$config->objectTables['story'] = TABLE_STORY;
$config->objectTables['requirement'] = TABLE_STORY;
$config->objectTables['release'] = TABLE_RELEASE;
$config->objectTables['program'] = TABLE_PROJECT;
$config->objectTables['project'] = TABLE_PROJECT;
$config->objectTables['execution'] = TABLE_PROJECT;
$config->objectTables['task'] = TABLE_TASK;
$config->objectTables['build'] = TABLE_BUILD;
$config->objectTables['bug'] = TABLE_BUG;
$config->objectTables['case'] = TABLE_CASE;
$config->objectTables['testcase'] = TABLE_CASE;
$config->objectTables['testtask'] = TABLE_TESTTASK;
$config->objectTables['testsuite'] = TABLE_TESTSUITE;
$config->objectTables['testreport'] = TABLE_TESTREPORT;
$config->objectTables['user'] = TABLE_USER;
$config->objectTables['api'] = TABLE_API;
$config->objectTables['doc'] = TABLE_DOC;
$config->objectTables['doclib'] = TABLE_DOCLIB;
$config->objectTables['todo'] = TABLE_TODO;
$config->objectTables['custom'] = TABLE_LANG;
$config->objectTables['branch'] = TABLE_BRANCH;
$config->objectTables['module'] = TABLE_MODULE;
$config->objectTables['caselib'] = TABLE_TESTSUITE;
$config->objectTables['entry'] = TABLE_ENTRY;
$config->objectTables['webhook'] = TABLE_WEBHOOK;
$config->objectTables['stakeholder'] = TABLE_STAKEHOLDER;
$config->objectTables['job'] = TABLE_JOB;
$config->objectTables['team'] = TABLE_TEAM;
$config->objectTables['pipeline'] = TABLE_PIPELINE;
$config->objectTables['mr'] = TABLE_MR;
$config->objectTables['product'] = TABLE_PRODUCT;
$config->objectTables['productplan'] = TABLE_PRODUCTPLAN;
$config->objectTables['story'] = TABLE_STORY;
$config->objectTables['requirement'] = TABLE_STORY;
$config->objectTables['release'] = TABLE_RELEASE;
$config->objectTables['program'] = TABLE_PROJECT;
$config->objectTables['project'] = TABLE_PROJECT;
$config->objectTables['execution'] = TABLE_PROJECT;
$config->objectTables['task'] = TABLE_TASK;
$config->objectTables['build'] = TABLE_BUILD;
$config->objectTables['bug'] = TABLE_BUG;
$config->objectTables['case'] = TABLE_CASE;
$config->objectTables['testcase'] = TABLE_CASE;
$config->objectTables['testtask'] = TABLE_TESTTASK;
$config->objectTables['testsuite'] = TABLE_TESTSUITE;
$config->objectTables['testreport'] = TABLE_TESTREPORT;
$config->objectTables['user'] = TABLE_USER;
$config->objectTables['api'] = TABLE_API;
$config->objectTables['doc'] = TABLE_DOC;
$config->objectTables['doclib'] = TABLE_DOCLIB;
$config->objectTables['todo'] = TABLE_TODO;
$config->objectTables['custom'] = TABLE_LANG;
$config->objectTables['branch'] = TABLE_BRANCH;
$config->objectTables['module'] = TABLE_MODULE;
$config->objectTables['caselib'] = TABLE_TESTSUITE;
$config->objectTables['entry'] = TABLE_ENTRY;
$config->objectTables['webhook'] = TABLE_WEBHOOK;
$config->objectTables['stakeholder'] = TABLE_STAKEHOLDER;
$config->objectTables['job'] = TABLE_JOB;
$config->objectTables['team'] = TABLE_TEAM;
$config->objectTables['pipeline'] = TABLE_PIPELINE;
$config->objectTables['mr'] = TABLE_MR;
$config->objectTables['kanbancolumn'] = TABLE_KANBANCOLUMN;
$config->objectTables['kanbanlane'] = TABLE_KANBANLANE;
$config->newFeatures = array('introduction', 'tutorial', 'youngBlueTheme');
/* Program privs.*/
$config->programPriv = new stdclass();
$config->programPriv->scrum = array('product', 'story', 'productplan', 'release', 'projectrelease', 'project', 'task', 'build', 'qa', 'bug', 'testcase', 'testsuite', 'testreport', 'caselib', 'doc', 'report', 'repo', 'svn', 'git', 'search', 'tree', 'file', 'jenkins', 'gitlab', 'job', 'ci', 'branch');
$config->programPriv->waterfall = $config->programPriv->scrum + array('workestimation', 'durationestimation', 'budget', 'programplan', 'review', 'reviewissue', 'weekly', 'milestone', 'design', 'issue', 'risk', 'auditplan', 'nc', 'cm', 'pssp');
$config->programPriv->scrum = array('projectstory', 'projectrelease', 'project', 'build', 'bug', 'testcase', 'testreport', 'caselib', 'doc', 'repo', 'meeting', 'stakeholder');
$config->programPriv->waterfall = array_merge($config->programPriv->scrum, array('workestimation', 'durationestimation', 'budget', 'programplan', 'review', 'reviewissue', 'weekly', 'milestone', 'design', 'issue', 'risk', 'opportunity', 'measrecord', 'auditplan', 'trainplan', 'gapanalysis', 'pssp'));
+137
View File
@@ -5,3 +5,140 @@ ALTER TABLE `zt_branch` ADD `createdDate` date NOT NULL AFTER `desc`;
ALTER TABLE `zt_branch` ADD `closedDate` date NOT NULL AFTER `createdDate`;
ALTER TABLE `zt_projectstory` ADD `branch` mediumint(8) NOT NULL AFTER `product`;
ALTER TABLE `zt_projectproduct` ADD PRIMARY KEY `project_product_branch` (`project`, `product`, `branch`), DROP INDEX `PRIMARY`;
-- DROP TABLE IF EXISTS `zt_kanbanlane`;
CREATE TABLE IF NOT EXISTS `zt_kanbanlane` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`execution` mediumint(8) NOT NULL DEFAULT '0',
`type` char(30) NOT NULL,
`groupby` char(30) NOT NULL,
`extra` char(30) NOT NULL,
`name` varchar(255) NOT NULL DEFAULT '',
`color` char(30) NOT NULL,
`order` smallint(6) NOT NULL DEFAULT '0',
`lastEditedTime` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_kanbancolumn`;
CREATE TABLE IF NOT EXISTS `zt_kanbancolumn` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`lane` mediumint(8) NOT NULL DEFAULT '0',
`parent` mediumint(8) NOT NULL DEFAULT '0',
`type` char(30) NOT NULL,
`name` varchar(255) NOT NULL DEFAULT '',
`color` char(30) NOT NULL,
`limit` smallint(6) NOT NULL DEFAULT '-1',
`order` mediumint(8) NOT NULL DEFAULT '0',
`cards` text NULL,
`deleted` enum('0','1') NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_stage`;
CREATE TABLE IF NOT EXISTS `zt_stage` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`percent` varchar(255) NOT NULL,
`type` varchar(255) NOT NULL,
`createdBy` varchar(30) NOT NULL,
`createdDate` datetime NOT NULL,
`editedBy` varchar(30) NOT NULL,
`editedDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_design`;
CREATE TABLE IF NOT EXISTS `zt_design` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`project` varchar(255) NOT NULL,
`product` varchar(255) NOT NULL,
`commit` text NOT NULL,
`commitedBy` varchar(30) NOT NULL,
`execution` mediumint(8) unsigned NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`status` varchar(30) NOT NULL,
`createdBy` varchar(30) NOT NULL,
`createdDate` datetime NOT NULL,
`editedBy` varchar(30) NOT NULL,
`editedDate` datetime NOT NULL,
`assignedTo` varchar(30) NOT NULL,
`assignedBy` varchar(30) NOT NULL,
`assignedDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
`story` char(30) NOT NULL,
`desc` text NOT NULL,
`version` smallint(6) NOT NULL,
`type` char(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_designspec`;
CREATE TABLE IF NOT EXISTS `zt_designspec` (
`design` mediumint(8) NOT NULL,
`version` smallint(6) NOT NULL,
`name` varchar(255) NOT NULL,
`desc` text NOT NULL,
`files` varchar(255) NOT NULL,
UNIQUE KEY `design` (`design`,`version`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_weeklyreport`;
CREATE TABLE IF NOT EXISTS `zt_weeklyreport`(
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`project` mediumint(8) unsigned NOT NULL,
`weekStart` date NOT NULL,
`pv` float(9,2) NOT NULL,
`ev` float(9,2) NOT NULL,
`ac` float(9,2) NOT NULL,
`sv` float(9,2) NOT NULL,
`cv` float(9,2) NOT NULL,
`staff` smallint(5) unsigned NOT NULL,
`progress` varchar(255) NOT NULL,
`workload` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `week` (`project`,`weekStart`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_holiday`;
CREATE TABLE IF NOT EXISTS `zt_holiday` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL DEFAULT '',
`type` enum('holiday', 'working') NOT NULL DEFAULT 'holiday',
`desc` text NOT NULL,
`year` char(4) NOT NULL,
`begin` date NOT NULL,
`end` date NOT NULL,
PRIMARY KEY (`id`),
KEY `year` (`year`),
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
REPLACE INTO `zt_stage` (`name`,`percent`,`type`,`createdBy`,`createdDate`,`editedBy`,`editedDate`,`deleted`) VALUES
('需求','10','request','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
('设计','10','design','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
('开发','50','dev','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
('测试','15','qa','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
('发布','10','release','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
('总结评审','5','review','admin','2020-02-08 21:08:45','admin','2020-02-12 13:50:27','0');
INSERT INTO `zt_lang` (`lang`, `module`, `section`, `key`, `value`, `system`) VALUES
('all','stage','typeList','request','需求', '1'),
('all','stage','typeList','design','设计', '1'),
('all','stage','typeList','dev','开发', '1'),
('all','stage','typeList','qa','测试', '1'),
('all','stage','typeList','release','发布', '1'),
('all','stage','typeList','review','总结评审','1'),
('all','stage','typeList','other','其他','1');
ALTER TABLE `zt_bug`
ADD `feedbackBy` varchar(100) NOT NULL AFTER `activatedDate`,
ADD `notifyEmail` varchar(100) NOT NULL AFTER `feedbackBy`;
ALTER TABLE `zt_story`
ADD `feedbackBy` varchar(100) NOT NULL AFTER `version`,
ADD `notifyEmail` varchar(100) NOT NULL AFTER `feedbackBy`;
ALTER TABLE `zt_product` ADD `reviewer` varchar(255) NOT NULL AFTER `whitelist`;
+204 -86
View File
@@ -30,99 +30,94 @@ CREATE TABLE IF NOT EXISTS `zt_action` (
KEY `objectID` (`objectID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_api_lib_release`;
CREATE TABLE `zt_api_lib_release`
(
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`lib` int UNSIGNED NOT NULL DEFAULT 0,
`desc` varchar(255) NOT NULL DEFAULT '',
`version` varchar(255) NOT NULL DEFAULT '',
`snap` mediumtext NOT NULL,
`addedBy` varchar(30) NOT NULL DEFAULT 0,
`addedDate` datetime NOT NULL,
PRIMARY KEY (`id`)
CREATE TABLE `zt_api_lib_release` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`lib` int UNSIGNED NOT NULL DEFAULT 0,
`desc` varchar(255) NOT NULL DEFAULT '',
`version` varchar(255) NOT NULL DEFAULT '',
`snap` mediumtext NOT NULL,
`addedBy` varchar(30) NOT NULL DEFAULT 0,
`addedDate` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_api`;
CREATE TABLE `zt_api`
(
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`product` varchar(255) NOT NULL DEFAULT '',
`lib` int UNSIGNED NOT NULL DEFAULT 0,
`module` int UNSIGNED NOT NULL DEFAULT 0,
`title` varchar(100) NOT NULL DEFAULT '',
`path` varchar(255) NOT NULL DEFAULT '',
`protocol` varchar(10) NOT NULL DEFAULT '',
`method` varchar(10) NOT NULL DEFAULT '',
`requestType` varchar(100) NOT NULL DEFAULT '',
`responseType` varchar(100) NOT NULL DEFAULT '',
`status` varchar(20) NOT NULL DEFAULT '',
`owner` varchar(30) NOT NULl DEFAULT 0,
`desc` text NULL,
`version` smallint UNSIGNED NOT NULL DEFAULT 0,
`params` text NULL,
`paramsExample` text NUll,
`responseExample` text NUll,
`response` text NULL,
`commonParams` text NULL,
`addedBy` varchar(30) NOT NULL DEFAULT 0,
`addedDate` datetime NOT NULL,
`editedBy` varchar(30) NOT NULL DEFAULT 0,
`editedDate` datetime NOT NULL,
`deleted` enum ('0', '1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
CREATE TABLE `zt_api` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`product` varchar(255) NOT NULL DEFAULT '',
`lib` int UNSIGNED NOT NULL DEFAULT 0,
`module` int UNSIGNED NOT NULL DEFAULT 0,
`title` varchar(100) NOT NULL DEFAULT '',
`path` varchar(255) NOT NULL DEFAULT '',
`protocol` varchar(10) NOT NULL DEFAULT '',
`method` varchar(10) NOT NULL DEFAULT '',
`requestType` varchar(100) NOT NULL DEFAULT '',
`responseType` varchar(100) NOT NULL DEFAULT '',
`status` varchar(20) NOT NULL DEFAULT '',
`owner` varchar(30) NOT NULl DEFAULT 0,
`desc` text NULL,
`version` smallint UNSIGNED NOT NULL DEFAULT 0,
`params` text NULL,
`paramsExample` text NUll,
`responseExample` text NUll,
`response` text NULL,
`commonParams` text NULL,
`addedBy` varchar(30) NOT NULL DEFAULT 0,
`addedDate` datetime NOT NULL,
`editedBy` varchar(30) NOT NULL DEFAULT 0,
`editedDate` datetime NOT NULL,
`deleted` enum ('0', '1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_apispec`;
CREATE TABLE `zt_apispec`
(
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`doc` int UNSIGNED NOT NULL DEFAULT 0,
`module` int UNSIGNED NOT NULL DEFAULT 0,
`title` varchar(100) NOT NULL DEFAULT '',
`path` varchar(255) NOT NULL DEFAULT '',
`protocol` varchar(10) NOT NULL DEFAULT '',
`method` varchar(10) NOT NULL DEFAULT '',
`requestType` varchar(100) NOT NULL DEFAULT '',
`responseType` varchar(100) NOT NULL DEFAULT '',
`status` varchar(20) NOT NULL DEFAULT '',
`owner` varchar(255) NOT NULl DEFAULT 0,
`desc` text NULL,
`version` smallint UNSIGNED NOT NULL DEFAULT 0,
`params` text NULL,
`paramsExample` text NUll,
`responseExample` text NUll,
`response` text NULL,
`addedBy` varchar(30) NOT NULL DEFAULT 0,
`addedDate` datetime NULL,
PRIMARY KEY (`id`)
CREATE TABLE `zt_apispec` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`doc` int UNSIGNED NOT NULL DEFAULT 0,
`module` int UNSIGNED NOT NULL DEFAULT 0,
`title` varchar(100) NOT NULL DEFAULT '',
`path` varchar(255) NOT NULL DEFAULT '',
`protocol` varchar(10) NOT NULL DEFAULT '',
`method` varchar(10) NOT NULL DEFAULT '',
`requestType` varchar(100) NOT NULL DEFAULT '',
`responseType` varchar(100) NOT NULL DEFAULT '',
`status` varchar(20) NOT NULL DEFAULT '',
`owner` varchar(255) NOT NULl DEFAULT 0,
`desc` text NULL,
`version` smallint UNSIGNED NOT NULL DEFAULT 0,
`params` text NULL,
`paramsExample` text NUll,
`responseExample` text NUll,
`response` text NULL,
`addedBy` varchar(30) NOT NULL DEFAULT 0,
`addedDate` datetime NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_apistruct`;
CREATE TABLE `zt_apistruct`
(
`id` int unsigned NOT NULL AUTO_INCREMENT,
`lib` int UNSIGNED NOT NULL DEFAULT 0,
`name` varchar(30) NOT NULL DEFAULT '',
`type` varchar(50) NOT NULL DEFAULT '',
`desc` text NOT NULL DEFAULT '',
`version` smallint unsigned NOT NULL DEFAULT 0,
`attribute` text NULL,
`addedBy` varchar(30) NOT NULL DEFAULT 0,
`addedDate` datetime NOT NULL,
`editEdBy` varchar(30) NOT NULL DEFAULT 0,
`editedDate` datetime NOT NULL,
`deleted` enum ('0', '1') NOT NULL DEFAULT '0',
primary key (`id`)
CREATE TABLE `zt_apistruct` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`lib` int UNSIGNED NOT NULL DEFAULT 0,
`name` varchar(30) NOT NULL DEFAULT '',
`type` varchar(50) NOT NULL DEFAULT '',
`desc` varchar(255) NOT NULL DEFAULT '',
`version` smallint unsigned NOT NULL DEFAULT 0,
`attribute` text NULL,
`addedBy` varchar(30) NOT NULL DEFAULT 0,
`addedDate` datetime NOT NULL,
`editEdBy` varchar(30) NOT NULL DEFAULT 0,
`editedDate` datetime NOT NULL,
`deleted` enum ('0', '1') NOT NULL DEFAULT '0',
primary key (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_apistruct_spec`;
CREATE TABLE `zt_apistruct_spec`
(
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`type` varchar(50) NOT NULL DEFAULT '',
`desc` varchar(255) NOT NULL DEFAULT '',
`attribute` text NULL,
`version` smallint unsigned NOT NULL DEFAULT 0,
`addedBy` varchar(30) NOT NULL DEFAULT 0,
`addedDate` datetime NOT NULL,
primary key (`id`)
CREATE TABLE `zt_apistruct_spec` (
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`type` varchar(50) NOT NULL DEFAULT '',
`desc` varchar(255) NOT NULL DEFAULT '',
`attribute` text NULL,
`version` smallint unsigned NOT NULL DEFAULT 0,
`addedBy` varchar(30) NOT NULL DEFAULT 0,
`addedDate` datetime NOT NULL,
primary key (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_block`;
CREATE TABLE IF NOT EXISTS `zt_block` (
@@ -187,6 +182,8 @@ CREATE TABLE IF NOT EXISTS `zt_bug` (
`confirmed` tinyint(1) NOT NULL default '0',
`activatedCount` smallint(6) NOT NULL,
`activatedDate` datetime NOT NULL,
`feedbackBy` varchar(100) NOT NULL,
`notifyEmail` varchar(100) NOT NULL,
`mailto` text,
`openedBy` varchar(30) NOT NULL default '',
`openedDate` datetime NOT NULL,
@@ -398,6 +395,39 @@ CREATE TABLE IF NOT EXISTS `zt_dept` (
KEY `parent` (`parent`),
KEY `path` (`path`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_design`;
CREATE TABLE IF NOT EXISTS `zt_design` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`project` varchar(255) NOT NULL,
`product` varchar(255) NOT NULL,
`commit` text NOT NULL,
`commitedBy` varchar(30) NOT NULL,
`execution` mediumint(8) unsigned NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`status` varchar(30) NOT NULL,
`createdBy` varchar(30) NOT NULL,
`createdDate` datetime NOT NULL,
`editedBy` varchar(30) NOT NULL,
`editedDate` datetime NOT NULL,
`assignedTo` varchar(30) NOT NULL,
`assignedBy` varchar(30) NOT NULL,
`assignedDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
`story` char(30) NOT NULL,
`desc` text NOT NULL,
`version` smallint(6) NOT NULL,
`type` char(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_designspec`;
CREATE TABLE IF NOT EXISTS `zt_designspec` (
`design` mediumint(8) NOT NULL,
`version` smallint(6) NOT NULL,
`name` varchar(255) NOT NULL,
`desc` text NOT NULL,
`files` varchar(255) NOT NULL,
UNIQUE KEY `design` (`design`,`version`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_doc`;
CREATE TABLE IF NOT EXISTS `zt_doc` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
@@ -563,6 +593,19 @@ CREATE TABLE IF NOT EXISTS `zt_grouppriv` (
`method` char(30) NOT NULL default '',
UNIQUE KEY `group` (`group`,`module`,`method`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_holiday`;
CREATE TABLE IF NOT EXISTS `zt_holiday` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL DEFAULT '',
`type` enum('holiday', 'working') NOT NULL DEFAULT 'holiday',
`desc` text NOT NULL,
`year` char(4) NOT NULL,
`begin` date NOT NULL,
`end` date NOT NULL,
PRIMARY KEY (`id`),
KEY `year` (`year`),
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_history`;
CREATE TABLE IF NOT EXISTS `zt_history` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
@@ -600,6 +643,34 @@ CREATE TABLE IF NOT EXISTS `zt_job` (
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_kanbanlane`;
CREATE TABLE IF NOT EXISTS `zt_kanbanlane` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`execution` mediumint(8) NOT NULL DEFAULT '0',
`type` char(30) NOT NULL,
`groupby` char(30) NOT NULL,
`extra` char(30) NOT NULL,
`name` varchar(255) NOT NULL DEFAULT '',
`color` char(30) NOT NULL,
`order` smallint(6) NOT NULL DEFAULT '0',
`lastEditedDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_kanbancolumn`;
CREATE TABLE IF NOT EXISTS `zt_kanbancolumn` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`lane` mediumint(8) NOT NULL DEFAULT '0',
`parent` mediumint(8) NOT NULL DEFAULT '0',
`type` char(30) NOT NULL,
`name` varchar(255) NOT NULL DEFAULT '',
`color` char(30) NOT NULL,
`limit` smallint(6) NOT NULL DEFAULT '-1',
`order` mediumint(8) NOT NULL DEFAULT '0',
`cards` text NULL,
`deleted` enum('0','1') NOT NULL default '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_lang`;
CREATE TABLE IF NOT EXISTS `zt_lang` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
@@ -738,6 +809,7 @@ CREATE TABLE IF NOT EXISTS `zt_product` (
`RD` varchar(30) NOT NULL,
`acl` enum('open','private','custom') NOT NULL default 'open',
`whitelist` text NOT NULL,
`reviewer` varchar(255) NOT NULL,
`createdBy` varchar(30) NOT NULL,
`createdDate` datetime NOT NULL,
`createdVersion` varchar(20) NOT NULL,
@@ -995,6 +1067,19 @@ CREATE TABLE IF NOT EXISTS `zt_searchindex` (
FULLTEXT KEY `content` (`content`),
FULLTEXT KEY `title` (`title`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_stage`;
CREATE TABLE IF NOT EXISTS `zt_stage` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`percent` varchar(255) NOT NULL,
`type` varchar(255) NOT NULL,
`createdBy` varchar(30) NOT NULL,
`createdDate` datetime NOT NULL,
`editedBy` varchar(30) NOT NULL,
`editedDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_stakeholder`;
CREATE TABLE IF NOT EXISTS `zt_stakeholder` (
`id` mediumint(8) NOT NULL AUTO_INCREMENT PRIMARY KEY,
@@ -1049,6 +1134,8 @@ CREATE TABLE IF NOT EXISTS `zt_story` (
`linkStories` varchar(255) NOT NULL,
`duplicateStory` mediumint(8) unsigned NOT NULL,
`version` smallint(6) NOT NULL default '1',
`feedbackBy` varchar(100) NOT NULL,
`notifyEmail` varchar(100) NOT NULL,
`URChanged` enum('0','1') NOT NULL DEFAULT '0',
`deleted` enum('0','1') NOT NULL default '0',
PRIMARY KEY (`id`),
@@ -1415,6 +1502,22 @@ CREATE TABLE IF NOT EXISTS `zt_userview` (
`sprints` mediumtext NOT NULL,
UNIQUE KEY `account` (`account`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_weeklyreport`;
CREATE TABLE IF NOT EXISTS `zt_weeklyreport`(
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`project` mediumint(8) unsigned NOT NULL,
`weekStart` date NOT NULL,
`pv` float(9,2) NOT NULL,
`ev` float(9,2) NOT NULL,
`ac` float(9,2) NOT NULL,
`sv` float(9,2) NOT NULL,
`cv` float(9,2) NOT NULL,
`staff` smallint(5) unsigned NOT NULL,
`progress` varchar(255) NOT NULL,
`workload` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `week` (`project`,`weekStart`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_webhook`;
CREATE TABLE IF NOT EXISTS `zt_webhook` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
@@ -5701,7 +5804,22 @@ REPLACE INTO `zt_lang` (`lang`, `module`, `section`, `key`, `value`, `system`) V
('zh-cn', 'custom', 'URSRList', '3', '{\"SRName\":\"\\u8f6f\\u9700\",\"URName\":\"\\u7528\\u9700\"}', '1'),('zh-cn', 'custom', 'URSRList', '4', '{\"SRName\":\"\\u6545\\u4e8b\",\"URName\":\"\\u53f2\\u8bd7\"}', '1'),
('zh-cn', 'custom', 'URSRList', '5', '{\"SRName\":\"\\u9700\\u6c42\",\"URName\":\"\\u7528\\u6237\\u9700\\u6c42\"}', '1'),
('en', 'custom', 'URSRList', '1', '{\"SRName\":\"Story\",\"URName\":\"Epic\"}', '0'),
('en', 'custom', 'URSRList', '2', '{\"SRName\":\"Software Requirement\",\"URName\":\"User Requirement\"}', '0');
('en', 'custom', 'URSRList', '2', '{\"SRName\":\"Software Requirement\",\"URName\":\"User Requirement\"}', '0'),
('all','stage','typeList','request','需求', '1'),
('all','stage','typeList','design','设计', '1'),
('all','stage','typeList','dev','开发', '1'),
('all','stage','typeList','qa','测试', '1'),
('all','stage','typeList','release','发布', '1'),
('all','stage','typeList','review','总结评审','1'),
('all','stage','typeList','other','其他','1');
REPLACE INTO `zt_stage` (`name`,`percent`,`type`,`createdBy`,`createdDate`,`editedBy`,`editedDate`,`deleted`) VALUES
('需求','10','request','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
('设计','10','design','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
('开发','50','dev','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
('测试','15','qa','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
('发布','10','release','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
('总结评审','5','review','admin','2020-02-08 21:08:45','admin','2020-02-12 13:50:27','0');
INSERT INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system', 'custom', '', 'hourPoint', '0');
INSERT INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system', 'common', '', 'CRProduct', '1');
+1 -4
View File
@@ -945,10 +945,7 @@ class baseControl
*/
public function sendError($error)
{
$this->send(array(
'result' => 'fail',
'message' => $error,
));
$this->send(array('result' => 'fail', 'message' => $error));
}
/**
+1 -2
View File
@@ -229,7 +229,7 @@ class html extends baseHTML
/**
* Create user avatar.
*
* @param string|object|array $user User object or user avatar url or user account
* @param string|object|array $user User object or user account
* @param string|int $size Avatar size, can be a number or preset sizes: "xs", "sm", "", "lg", "xl", default is ""
* @param string $className Avatar element class name, default is "avatar-circle"
* @param string $attrib Extra attributes on avatar element
@@ -248,7 +248,6 @@ class html extends baseHTML
if(is_string($user))
{
$userObj->account = $user;
if(strlen($user) > 1) $userObj->avatar = $user;
$user = $userObj;
}
elseif(is_array($user))
-4
View File
@@ -90,14 +90,10 @@ class gitlab
/**
* Get files info.
*
* The API path requested is: "GET /projects/:id/repository/files/:file_path".
* Known issue of GitLab API: if a '%' in 'file_path', GitLab API will show a error 'file_path should be a valid file path'.
*
* @param string $path
* @param string $ref
* @access public
* @return array
* @doc https://docs.gitlab.com/ee/api/repository_files.html
*/
public function files($path, $ref = 'master')
{
+36 -34
View File
@@ -1,37 +1,39 @@
<?php
$config->action->objectNameFields['product'] = 'name';
$config->action->objectNameFields['story'] = 'title';
$config->action->objectNameFields['productplan'] = 'title';
$config->action->objectNameFields['release'] = 'name';
$config->action->objectNameFields['program'] = 'name';
$config->action->objectNameFields['project'] = 'name';
$config->action->objectNameFields['execution'] = 'name';
$config->action->objectNameFields['task'] = 'name';
$config->action->objectNameFields['build'] = 'name';
$config->action->objectNameFields['bug'] = 'title';
$config->action->objectNameFields['testcase'] = 'title';
$config->action->objectNameFields['case'] = 'title';
$config->action->objectNameFields['testtask'] = 'name';
$config->action->objectNameFields['user'] = 'account';
$config->action->objectNameFields['api'] = 'title';
$config->action->objectNameFields['doc'] = 'title';
$config->action->objectNameFields['doclib'] = 'name';
$config->action->objectNameFields['todo'] = 'name';
$config->action->objectNameFields['branch'] = 'name';
$config->action->objectNameFields['module'] = 'name';
$config->action->objectNameFields['testsuite'] = 'name';
$config->action->objectNameFields['caselib'] = 'name';
$config->action->objectNameFields['testreport'] = 'title';
$config->action->objectNameFields['entry'] = 'name';
$config->action->objectNameFields['webhook'] = 'name';
$config->action->objectNameFields['risk'] = 'name';
$config->action->objectNameFields['issue'] = 'title';
$config->action->objectNameFields['design'] = 'name';
$config->action->objectNameFields['stakeholder'] = 'user';
$config->action->objectNameFields['budget'] = 'name';
$config->action->objectNameFields['job'] = 'name';
$config->action->objectNameFields['team'] = 'name';
$config->action->objectNameFields['pipeline'] = 'name';
$config->action->objectNameFields['product'] = 'name';
$config->action->objectNameFields['story'] = 'title';
$config->action->objectNameFields['productplan'] = 'title';
$config->action->objectNameFields['release'] = 'name';
$config->action->objectNameFields['program'] = 'name';
$config->action->objectNameFields['project'] = 'name';
$config->action->objectNameFields['execution'] = 'name';
$config->action->objectNameFields['task'] = 'name';
$config->action->objectNameFields['build'] = 'name';
$config->action->objectNameFields['bug'] = 'title';
$config->action->objectNameFields['testcase'] = 'title';
$config->action->objectNameFields['case'] = 'title';
$config->action->objectNameFields['testtask'] = 'name';
$config->action->objectNameFields['user'] = 'account';
$config->action->objectNameFields['api'] = 'title';
$config->action->objectNameFields['doc'] = 'title';
$config->action->objectNameFields['doclib'] = 'name';
$config->action->objectNameFields['todo'] = 'name';
$config->action->objectNameFields['branch'] = 'name';
$config->action->objectNameFields['module'] = 'name';
$config->action->objectNameFields['testsuite'] = 'name';
$config->action->objectNameFields['caselib'] = 'name';
$config->action->objectNameFields['testreport'] = 'title';
$config->action->objectNameFields['entry'] = 'name';
$config->action->objectNameFields['webhook'] = 'name';
$config->action->objectNameFields['risk'] = 'name';
$config->action->objectNameFields['issue'] = 'title';
$config->action->objectNameFields['design'] = 'name';
$config->action->objectNameFields['stakeholder'] = 'user';
$config->action->objectNameFields['budget'] = 'name';
$config->action->objectNameFields['job'] = 'name';
$config->action->objectNameFields['team'] = 'name';
$config->action->objectNameFields['pipeline'] = 'name';
$config->action->objectNameFields['kanbancolumn'] = 'name';
$config->action->objectNameFields['kanbanlane'] = 'name';
$config->action->commonImgSize = 870;
@@ -46,5 +48,5 @@ $config->action->majorList['project'] = array('opened', 'edited');
$config->action->majorList['execution'] = array('opened', 'edited');
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,branch,';
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,';
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,pipeline,jenkins,';
+26 -21
View File
@@ -369,6 +369,10 @@ $lang->action->dynamicAction->execution['undeleted'] = 'Restore ' . $lang->execu
$lang->action->dynamicAction->execution['hidden'] = 'Hide ' . $lang->executionCommon;
$lang->action->dynamicAction->execution['moved'] = 'Improt Task';
$lang->action->dynamicAction->kanbancolumn['edited'] = 'Column Settings';
$lang->action->dynamicAction->kanbanlane['edited'] = 'Swimlane Settings';
$lang->action->dynamicAction->kanbanlane['moved'] = 'Move Swimlane';
$lang->action->dynamicAction->team['managedTeam'] = 'Manage Team';
$lang->action->dynamicAction->task['opened'] = 'Create Task';
@@ -500,27 +504,28 @@ else
{
$lang->action->label->execution = "$lang->executionCommon|execution|task|executionID=%s";
}
$lang->action->label->task = 'Task|task|view|taskID=%s';
$lang->action->label->build = 'Build|build|view|buildID=%s';
$lang->action->label->bug = 'Bug|bug|view|bugID=%s';
$lang->action->label->case = 'Case|testcase|view|caseID=%s';
$lang->action->label->testtask = 'Request|testtask|view|caseID=%s';
$lang->action->label->testsuite = 'Test Suite|testsuite|view|suiteID=%s';
$lang->action->label->caselib = 'Case Library|caselib|view|libID=%s';
$lang->action->label->todo = 'Todo|todo|view|todoID=%s';
$lang->action->label->doclib = 'Doc Library|doc|objectLibs|type=%s&objectID=%s&libID=%s&docID=&version=&appendLib=%s';
$lang->action->label->doc = 'Doc|doc|view|docID=%s';
$lang->action->label->user = 'User|user|view|account=%s';
$lang->action->label->testreport = 'Report|testreport|view|report=%s';
$lang->action->label->entry = 'Application|entry|browse|';
$lang->action->label->webhook = 'Webhook|webhook|browse|';
$lang->action->label->space = ' ';
$lang->action->label->risk = 'Risk|risk|view|riskID=%s';
$lang->action->label->issue = 'Issue|issue|view|issueID=%s';
$lang->action->label->design = 'Design|design|view|designID=%s';
$lang->action->label->stakeholder = 'Stakeholder|stakeholder|view|userID=%s';
$lang->action->label->api = 'Interface|api|index|libID=%s&moduleID=%s&apiID=%s';
$lang->action->label->branch = 'Branch|branch|manage|prouctID=%s&browseType=all';
$lang->action->label->task = 'Task|task|view|taskID=%s';
$lang->action->label->build = 'Build|build|view|buildID=%s';
$lang->action->label->bug = 'Bug|bug|view|bugID=%s';
$lang->action->label->case = 'Case|testcase|view|caseID=%s';
$lang->action->label->testtask = 'Request|testtask|view|caseID=%s';
$lang->action->label->testsuite = 'Test Suite|testsuite|view|suiteID=%s';
$lang->action->label->caselib = 'Case Library|caselib|view|libID=%s';
$lang->action->label->todo = 'Todo|todo|view|todoID=%s';
$lang->action->label->doclib = 'Doc Library|doc|objectLibs|type=%s&objectID=%s&libID=%s';
$lang->action->label->doc = 'Doc|doc|view|docID=%s';
$lang->action->label->user = 'User|user|view|account=%s';
$lang->action->label->testreport = 'Report|testreport|view|report=%s';
$lang->action->label->entry = 'Application|entry|browse|';
$lang->action->label->webhook = 'Webhook|webhook|browse|';
$lang->action->label->space = ' ';
$lang->action->label->risk = 'Risk|risk|view|riskID=%s';
$lang->action->label->issue = 'Issue|issue|view|issueID=%s';
$lang->action->label->design = 'Design|design|view|designID=%s';
$lang->action->label->stakeholder = 'Stakeholder|stakeholder|view|userID=%s';
$lang->action->label->api = 'Interface|api|index|libID=%s&moduleID=%s&apiID=%s';
$lang->action->label->kanbancolumn = 'Kanban column|execution|kanban|execution=%s';
$lang->action->label->kanbanlane = 'Kanban Lane|execution|kanban|execution=%s&type=all';
/* Object type. */
$lang->action->search = new stdclass();
+26 -21
View File
@@ -372,6 +372,10 @@ $lang->action->dynamicAction->execution['undeleted'] = '还原' . $lang->executi
$lang->action->dynamicAction->execution['hidden'] = '隐藏' . $lang->executionCommon;
$lang->action->dynamicAction->execution['moved'] = '导入任务';
$lang->action->dynamicAction->kanbancolumn['edited'] = '设置看板列';
$lang->action->dynamicAction->kanbanlane['edited'] = '设置泳道';
$lang->action->dynamicAction->kanbanlane['moved'] = '移动泳道';
$lang->action->dynamicAction->team['managedTeam'] = '维护团队';
$lang->action->dynamicAction->task['opened'] = '创建任务';
@@ -503,27 +507,28 @@ else
{
$lang->action->label->execution = "$lang->executionCommon|execution|task|executionID=%s";
}
$lang->action->label->task = '任务|task|view|taskID=%s';
$lang->action->label->build = '版本|build|view|buildID=%s';
$lang->action->label->bug = 'Bug|bug|view|bugID=%s';
$lang->action->label->case = '用例|testcase|view|caseID=%s';
$lang->action->label->testtask = '测试单|testtask|view|caseID=%s';
$lang->action->label->testsuite = '测试套件|testsuite|view|suiteID=%s';
$lang->action->label->caselib = '用例库|caselib|view|libID=%s';
$lang->action->label->todo = '待办|todo|view|todoID=%s';
$lang->action->label->doclib = '文档库|doc|tablecontents|type=%s&objectID=%s&libID=%s';
$lang->action->label->doc = '文档|doc|view|docID=%s';
$lang->action->label->user = '用户|user|view|account=%s';
$lang->action->label->testreport = '报告|testreport|view|report=%s';
$lang->action->label->entry = '应用|entry|browse|';
$lang->action->label->webhook = 'Webhook|webhook|browse|';
$lang->action->label->space = ' ';
$lang->action->label->risk = '风险|risk|view|riskID=%s';
$lang->action->label->issue = '问题|issue|view|issueID=%s';
$lang->action->label->design = '设计|design|view|designID=%s';
$lang->action->label->stakeholder = '干系人|stakeholder|view|userID=%s';
$lang->action->label->api = '接口|api|index|libID=%s&moduleID=%s&apiID=%s';
$lang->action->label->branch = '分支|branch|manage|productID=%s&browseType=all';
$lang->action->label->task = '任务|task|view|taskID=%s';
$lang->action->label->build = '版本|build|view|buildID=%s';
$lang->action->label->bug = 'Bug|bug|view|bugID=%s';
$lang->action->label->case = '用例|testcase|view|caseID=%s';
$lang->action->label->testtask = '测试单|testtask|view|caseID=%s';
$lang->action->label->testsuite = '测试套件|testsuite|view|suiteID=%s';
$lang->action->label->caselib = '用例库|caselib|view|libID=%s';
$lang->action->label->todo = '待办|todo|view|todoID=%s';
$lang->action->label->doclib = '文档库|doc|tablecontents|type=%s&objectID=%s&libID=%s';
$lang->action->label->doc = '文档|doc|view|docID=%s';
$lang->action->label->user = '用户|user|view|account=%s';
$lang->action->label->testreport = '报告|testreport|view|report=%s';
$lang->action->label->entry = '应用|entry|browse|';
$lang->action->label->webhook = 'Webhook|webhook|browse|';
$lang->action->label->space = ' ';
$lang->action->label->risk = '风险|risk|view|riskID=%s';
$lang->action->label->issue = '问题|issue|view|issueID=%s';
$lang->action->label->design = '设计|design|view|designID=%s';
$lang->action->label->stakeholder = '干系人|stakeholder|view|userID=%s';
$lang->action->label->api = '接口|api|index|libID=%s&moduleID=%s&apiID=%s';
$lang->action->label->kanbancolumn = '看板列|execution|kanban|execution=%s';
$lang->action->label->kanbanlane = '看板泳道|execution|kanban|execution=%s&type=all';
/* Object type. */
$lang->action->search = new stdclass();
+26 -6
View File
@@ -66,8 +66,6 @@ class actionModel extends model
$action->product = $relation['product'];
$action->project = (int)$relation['project'];
$action->execution = (int)$relation['execution'];
$this->dao->insert(TABLE_ACTION)->data($action)->autoCheck()->exec();
$actionID = $this->dao->lastInsertID();
@@ -190,7 +188,7 @@ class actionModel extends model
$fields = '*';
if(strpos('story, productplan, case, branch', $objectType) !== false) $fields = 'product';
if(strpos('build, bug, testtask, doc', $objectType) !== false) $fields = 'product, project, execution';
if(strpos('case, repo', $objectType) !== false) $fields = 'execution';
if(strpos('case, repo, kanbanlane', $objectType) !== false) $fields = 'execution';
if($objectType == 'release') $fields = 'product, build';
if($objectType == 'task') $fields = 'project, execution, story';
@@ -199,6 +197,8 @@ class actionModel extends model
/* Process story, release and task. */
if($objectType == 'story') $record->project = $this->dao->select('project')->from(TABLE_PROJECTSTORY)->where('story')->eq($objectID)->orderBy('project_desc')->limit(1)->fetch('project');
if($objectType == 'release') $record->project = $this->dao->select('project')->from(TABLE_BUILD)->where('id')->eq($record->build)->fetch('project');
if($objectType == 'kanbanlane') $record->execution = $this->dao->select($fields)->from(TABLE_KANBANLANE)->where('id')->eq($objectID)->fetch('execution');
if($objectType == 'kanbancolumn') $record->execution = $extra;
if($objectType == 'team')
{
$team = $this->dao->select('type')->from(TABLE_PROJECT)->where('id')->eq($objectID)->fetch();
@@ -818,7 +818,7 @@ class actionModel extends model
if(!$actions) return array();
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'action');
return $this->transformActions($actions);;
return $this->transformActions($actions);
}
/**
@@ -1199,6 +1199,10 @@ class actionModel extends model
{
$params = sprintf($vars, trim($action->product, ','));
}
elseif($action->objectType == 'kanbancolumn' or $action->objectType == 'kanbanlane')
{
$params = sprintf($vars, $action->extra);
}
else
{
$params = sprintf($vars, $action->objectID);
@@ -1233,6 +1237,11 @@ class actionModel extends model
if($action->objectType == 'stakeholder' and $action->project == 0) $action->objectLink = '';
if($action->objectType == 'story' and $action->action == 'import2storylib')
{
$action->objectLink = helper::createLink('assetlib', 'storyView', "storyID=$action->objectID");
}
return $action;
}
@@ -1436,10 +1445,11 @@ class actionModel extends model
* @param array $actions
* @param string $direction
* @param string $type all|today|yesterday|thisweek|lastweek|thismonth|lastmonth
* @param string $orderBy date_desc|date_asc
* @access public
* @return array
*/
public function buildDateGroup($actions, $direction = 'next', $type = 'today')
public function buildDateGroup($actions, $direction = 'next', $type = 'today', $orderBy = 'date_desc')
{
$dateGroup = array();
foreach($actions as $action)
@@ -1467,7 +1477,17 @@ class actionModel extends model
}
}
if($direction != 'next') $dateGroup = array_reverse($dateGroup);
/* Modify date to the corrret order. */
if($this->app->rawModule != 'company' and $direction != 'next')
{
$dateGroup = array_reverse($dateGroup);
}
elseif($this->app->rawModule == 'company' and (($direction == 'next' and $orderBy == 'date_asc') or ($direction == 'pre' and $orderBy == 'date_desc')))
{
$dateGroup = array_reverse($dateGroup);
foreach($dateGroup as $key => $dateItem) $dateGroup[$key] = array_reverse($dateItem);
}
return $dateGroup;
}
+7 -17
View File
@@ -67,7 +67,7 @@ class api extends control
$this->view->apiList = $apiList;
}
$this->setMenu($libID, $moduleID);
$this->setMenu($libID);
$this->view->isRelease = $release > 0;
$this->view->release = $release;
@@ -435,21 +435,17 @@ class api extends control
$this->setMenu($api->lib);
$example = array('example' => 'type,description');
$example = json_encode($example, JSON_PRETTY_PRINT);
$options = array();
foreach($this->lang->api->paramsTypeOptions as $key => $item)
{
$options[] = array('label' => $item, 'value' => $key);
}
$this->view->typeOptions = $options;
$this->view->gobackLink = $this->createLink('api', 'index', "libID={$api->lib}&moduleID={$api->module}");
$this->view->user = $this->app->user->account;
$this->view->allUsers = $this->loadModel('user')->getPairs('devfirst|noclosed');;
$this->view->typeOptions = $options;
$this->view->gobackLink = $this->createLink('api', 'index', "libID={$api->lib}&moduleID={$api->module}");
$this->view->user = $this->app->user->account;
$this->view->allUsers = $this->loadModel('user')->getPairs('devfirst|noclosed');;
$this->view->moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($api->lib, 'api', $startModuleID = 0);
$this->view->moduleID = $api->module ? (int)$api->module : (int)$this->cookie->lastDocModule;
$this->view->example = $example;
$this->view->title = $api->title . $this->lang->api->edit;
$this->display();
@@ -469,7 +465,6 @@ class api extends control
{
$now = helper::now();
$params = fixer::input('post')
->trim('title,path')
->remove('type')
->skipSpecial('params,response')
->add('addedBy', $this->app->user->account)
@@ -495,9 +490,6 @@ class api extends control
$lib = $this->doc->getLibByID($libID);
$libName = isset($lib->name) ? $lib->name . $this->lang->colon : '';
$example = array('example' => 'type,description');
$example = json_encode($example, JSON_PRETTY_PRINT);
$this->getTypeOptions($libID);
$this->view->gobackLink = $this->createLink('api', 'index', "libID=$libID&moduleID=$moduleID");
$this->view->user = $this->app->user->account;
@@ -507,7 +499,6 @@ class api extends control
$this->view->moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($libID, 'api', $startModuleID = 0);
$this->view->moduleID = $moduleID ? (int)$moduleID : (int)$this->cookie->lastDocModule;
$this->view->libs = $libs;
$this->view->example = $example;
$this->view->title = $libName . $this->lang->api->create;
$this->view->users = $this->user->getPairs('nocode');
@@ -613,11 +604,10 @@ class api extends control
* Set doc menu by method name.
*
* @param int $libID
* @param int $moduleID
* @access public
* @return void
*/
private function setMenu($libID = 0, $moduleID = 0)
private function setMenu($libID = 0)
{
common::setMenuVars('doc', $libID);
@@ -642,7 +632,7 @@ class api extends control
if(common::hasPriv('api', 'create'))
{
$menu .= "<li>";
$menu .= html::a(helper::createLink('api', 'create', "libID=$libID&moduleID=$moduleID"), "<i class='icon-rich-text icon'></i> " . $this->lang->api->apiDoc, '', "data-app='{$this->app->tab}'");
$menu .= html::a(helper::createLink('api', 'create', "libID=$libID"), "<i class='icon-rich-text icon'></i> " . $this->lang->api->apiDoc, '', "data-app='{$this->app->tab}'");
$menu .= "</li>";
}
+48 -48
View File
@@ -14,53 +14,53 @@ $lang->api->common = 'API';
$lang->api->getModel = 'Super Model API';
$lang->api->sql = 'SQL Query API';
$lang->api->index = 'Api Doc Home';
$lang->api->editLib = 'Edit Api Doc';
$lang->api->releases = 'Releases';
$lang->api->index = 'Home';
$lang->api->editLib = 'Edit';
$lang->api->releases = 'Release';
$lang->api->deleteRelease = 'Delete Release';
$lang->api->deleteLib = 'Delete Api Doc';
$lang->api->deleteLib = 'Delete API Doc';
$lang->api->createRelease = 'Publish';
$lang->api->createLib = 'Create Api Library';
$lang->api->createApi = 'Create Api';
$lang->api->createLib = 'Create API Library';
$lang->api->createApi = 'Create API Document';
$lang->api->createAB = 'Create';
$lang->api->edit = 'Edit';
$lang->api->delete = 'Delete';
$lang->api->position = 'Positions';
$lang->api->position = 'Position';
$lang->api->startLine = "%s,%s";
$lang->api->desc = 'Description';
$lang->api->debug = 'Debug';
$lang->api->submit = 'Submit';
$lang->api->url = 'Url';
$lang->api->url = 'URL';
$lang->api->result = 'Result';
$lang->api->status = 'Status';
$lang->api->data = 'Content';
$lang->api->noParam = 'Get debugging does not require input parameters,';
$lang->api->noModule = 'There is no directory under the interface library. Please maintain the directory first';
$lang->api->noModule = 'No directory in the API library. Please add the directory first';
$lang->api->post = 'Please refer to the page form for post debugging';
$lang->api->noUniqueName = 'Api library name already exists。';
$lang->api->noUniqueVersion = 'Version already exists。';
$lang->api->noUniqueName = 'The API library name exists.';
$lang->api->noUniqueVersion = 'The version exists.';
$lang->api->version = 'Version';
$lang->api->createStruct = 'Create Data Structure';
$lang->api->editStruct = 'Edit Data Structure';
$lang->api->deleteStruct = 'Delete Data Structure';
$lang->api->create = 'Ceate Doc';
$lang->api->title = 'Interface Name';
$lang->api->pageTitle = 'Api Library';
$lang->api->create = 'Create API';
$lang->api->title = 'Name';
$lang->api->pageTitle = 'API Library';
$lang->api->module = 'Directory';
$lang->api->apiDoc = 'Interface';
$lang->api->apiDoc = 'API';
$lang->api->manageType = 'Manage Directory';
$lang->api->managePublish = 'Manage Version';
$lang->api->doing = 'Doing';
$lang->api->done = 'Done';
$lang->api->basicInfo = 'Essential Information';
$lang->api->apiDesc = 'Interface Description';
$lang->api->confirmDelete = "Are you sure to delete this interface?";
$lang->api->confirmDeleteLib = "Are you sure to delete this interface library?";
$lang->api->basicInfo = 'Basic Information';
$lang->api->apiDesc = 'Description';
$lang->api->confirmDelete = "Do you want to delete this API?";
$lang->api->confirmDeleteLib = "Do you want to delete this interface library?";
$lang->api->filterStruct = "use struct";
$lang->api->defaultVersion = "Current Version";
/* Common access control lang. */
$lang->api->whiteList = 'White list';
$lang->api->whiteList = 'Whitelist';
$lang->api->aclList['open'] = 'Open';
$lang->api->aclList['private'] = 'Private';
$lang->api->aclList['custom'] = 'Custom';
@@ -68,9 +68,9 @@ $lang->api->group = 'Group';
$lang->api->user = 'User';
$lang->api->noticeAcl = array(
'open' => 'Users who can access the api library which the library belongs can access it.',
'custom' => 'Users in the whiltelist can access it.',
'private' => 'Only the one who created it can access it.',
'open' => 'Users who can access the API library can access it.',
'custom' => 'Users on the whiltelist can access it.',
'private' => 'Only the one who creates it can access it.',
);
/* fields of struct */
@@ -81,7 +81,7 @@ $lang->struct->field = 'Field';
$lang->struct->paramsType = 'Type';
$lang->struct->required = 'Require';
$lang->struct->desc = 'Description';
$lang->struct->descPlaceholder = 'Parameter description';
$lang->struct->descPlaceholder = 'Parameter Description';
$lang->struct->action = 'Action';
$lang->struct->addSubField = 'Add Subfield';
@@ -94,36 +94,36 @@ $lang->struct->typeOptions = array(
/* fields of form */
$lang->api->struct = 'Data Structure';
$lang->api->structName = 'Structure Name';
$lang->api->structName = 'Name';
$lang->api->structType = 'Type';
$lang->api->structAttr = 'Attribute';
$lang->api->structAddedBy = 'Creator';
$lang->api->structAddedDate = 'Created Time';
$lang->api->name = 'Interface Library Name';
$lang->api->baseUrl = 'Base Url';
$lang->api->baseUrlDesc = 'Site or path. for example, api.zentao.com or /v1';
$lang->api->structAddedBy = 'CreatedBy';
$lang->api->structAddedDate = 'Created';
$lang->api->name = 'API Library Name';
$lang->api->baseUrl = 'Base URL';
$lang->api->baseUrlDesc = 'Site or path, e.g., api.zentao.com or /v1.';
$lang->api->desc = 'Description';
$lang->api->control = 'Access Control';
$lang->api->noLib = 'There is no interface library at present。';
$lang->api->noApi = 'There is no interface for the time being。';
$lang->api->noStruct = 'There is no structure for the time being。';
$lang->api->lib = 'Interface Library';
$lang->api->apiList = 'Interface List';
$lang->api->formTitle = 'Interface Name';
$lang->api->noLib = 'No API library yet.';
$lang->api->noApi = 'No API yet.';
$lang->api->noStruct = 'No API yet.';
$lang->api->lib = 'API Library';
$lang->api->apiList = 'API List';
$lang->api->formTitle = 'API Name';
$lang->api->path = 'Request Path';
$lang->api->protocol = 'Request Protocol';
$lang->api->method = 'Request Method';
$lang->api->requestType = 'Request Type';
$lang->api->status = 'Development Status';
$lang->api->owner = 'Person In Charge';
$lang->api->paramsExample = 'Response Example';
$lang->api->protocol = 'Protocol';
$lang->api->method = 'Method';
$lang->api->requestType = 'Type';
$lang->api->status = 'Status';
$lang->api->owner = 'Owner';
$lang->api->paramsExample = 'Request Example';
$lang->api->header = 'Request Header';
$lang->api->query = 'Request Parameters';
$lang->api->query = 'Parameter';
$lang->api->params = 'Request Body';
$lang->api->response = 'Response';
$lang->api->responseExample = 'Response Example';
$lang->api->res = new stdClass();
$lang->api->res->name = '名称';
$lang->api->res->name = 'Name';
$lang->api->res->desc = 'Description';
$lang->api->res->type = 'Type';
$lang->api->req = new stdClass();
@@ -198,14 +198,14 @@ $lang->api->allParamsTypeOptions = array_merge($lang->api->paramsTypeOptions, $l
$lang->api->requiredOptions = array(0 => 'No', 1 => 'Yes');
$lang->doclib = new stdclass();
$lang->doclib->name = 'Interface Library Name';
$lang->doclib->name = 'API Library Name';
$lang->apistruct = new stdClass();
$lang->apistruct->name = 'Structure Name';
$lang->apistruct->name = 'Name';
$lang->api_lib_release = new stdClass();
$lang->api_lib_release->version = 'Version';
$lang->api->error = new stdclass();
$lang->api->error->onlySelect = 'SQL interface only allow SELECT query.';
$lang->api->error->disabled = 'For security reasons, this feature is disabled. You can go to the config directory and modify the configuration item %s to open this function.';
$lang->api->error->onlySelect = 'SQL API only allows SELECT query.';
$lang->api->error->disabled = 'For security reasons, this feature is disabled. Go to the config directory and modify the configuration item %s to enable it.';
+1 -1
View File
@@ -41,7 +41,7 @@ $lang->api->noUniqueName = '接口库名已存在。';
$lang->api->noUniqueVersion = '版本已存在。';
$lang->api->version = '版本';
$lang->api->createStruct = '创建数据结构';
$lang->api->editStruct = '编辑数据结构';
$lang->api->editStruct = '修改数据结构';
$lang->api->deleteStruct = '删除数据结构';
$lang->api->create = '创建接口';
$lang->api->title = '接口名称';
+9 -10
View File
@@ -209,29 +209,28 @@ class apiModel extends model
$now = helper::now();
$account = $this->app->user->account;
$data = fixer::input('post')
->remove('type')
->skipSpecial('params,response')
->add('editedBy', $account)
->add('editedDate', $now)
->add('version', $oldApi->version)
->setDefault('product,module', 0)
->remove('type')
->get();
$changes = common::createChanges($oldApi, $data);
if(!empty($changes)) $data->version = $oldApi->version + 1;
$data->id = $oldApi->id;
$data->version = $oldApi->version + 1;
$apiSpec = $this->getApiSpecByData($data);
$this->dao->replace(TABLE_API_SPEC)->data($apiSpec)->exec();
unset($data->id);
$this->dao->update(TABLE_API)
->data($data)
->autoCheck()
->batchCheck($this->config->api->edit->requiredFields, 'notempty')
->where('id')->eq($apiID)
->exec();
$data->id = $apiID;
$apiSpec = $this->getApiSpecByData($data);
$this->dao->replace(TABLE_API_SPEC)->data($apiSpec)->exec();
return $changes;
return common::createChanges($oldApi, $data);
}
/**
+2 -9
View File
@@ -1,4 +1,4 @@
<div class="main-col" data-min-width="500">
<div class="main-col" data-min-width="400">
<div id="mainContent" class="main-row in">
<div class="main-col col-8">
<div class="cell" id="content">
@@ -95,14 +95,7 @@
$field = '';
for($i = 0; $i < $level; $i++)
{
if($i + 1 < $level)
{
$field .= '&nbsp;&nbsp;&nbsp;&nbsp;';
}
else
{
$field .= '&nbsp;&nbsp;∟&nbsp;&nbsp;';
}
$field .= '&nbsp;&nbsp;∟&nbsp;&nbsp;';
}
$field .= $data['field'];
$str .= '<td>' . $field . '</td>';
+1 -2
View File
@@ -12,7 +12,6 @@
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('example', $example);?>
<?php js::set('libID', $libID);?>
<?php
js::set('typeOptions', $typeOptions);
@@ -69,7 +68,7 @@ js::set('struct_paramsType', $lang->struct->paramsType);
<tr>
<th><?php echo $lang->api->module;?></th>
<td>
<span id='moduleBox'><?php echo html::select('module', $moduleOptionMenu, $moduleID, "class='form-control chosen'");?></span>
<span id='moduleBox'><?php echo html::select('module', $moduleOptionMenu, '', "class='form-control chosen'");?></span>
</td>
<td></td>
</tr>
-1
View File
@@ -13,7 +13,6 @@
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::import($jsRoot . 'vue/vue.js');?>
<?php js::set('example', $example);?>
<?php js::set('libID', $api->lib);?>
<?php
js::set('typeOptions', $typeOptions);
+1 -3
View File
@@ -42,10 +42,8 @@
</div>
<?php if(!$moduleTree):?>
<hr class="space">
<?php if(!$isRelease):?>
<div class="text-center text-muted tips"><?php echo $lang->api->noModule;?></div>
<?php endif;?>
<?php endif;?>
<?php echo $moduleTree;?>
</div>
</div>
@@ -73,7 +71,7 @@
</div>
</div>
<?php else:?>
<div class="cell main-col" data-min-width="400">
<div class="cell">
<div class="detail">
<ul class="list-group">
<?php foreach($apiList as $api):?>
+1 -1
View File
@@ -41,7 +41,7 @@
<td><?php echo zget($users, $release->addedBy, '');?></td>
<td class="c-date"><?php echo $release->addedDate;?></td>
<td class='c-actions'>
<?php if(common::hasPriv('api', 'deleteRelease')) echo html::a($this->createLink('api', 'deleteRelease', "libID=$libID&id=$release->id"), '<i class="icon-trash"></i>', 'hiddenwin', "title='{$lang->api->deleteRelease}' class='btn'");?>
<?php echo html::a($this->createLink('api', 'deleteRelease', "libID=$libID&id=$release->id"), '<i class="icon-trash"></i>', 'hiddenwin', "title='{$lang->api->delete}' class='btn'");?>
</td>
</tr>
<?php endforeach;?>
+2 -2
View File
@@ -49,8 +49,8 @@
<td class="c-date"><?php echo $struct->addedDate;?></td>
<td class='c-actions'>
<?php
if(common::hasPriv('api', 'editStruct')) echo html::a($this->createLink('api', 'editStruct', "libID=$libID&structID=$struct->id"), '<i class="icon-edit"></i>', '', "title='{$lang->api->editStruct}' class='btn'");
if(common::hasPriv('api', 'deleteStruct')) echo html::a($this->createLink('api', 'deleteStruct', "libID=$libID&structID=$struct->id"), '<i class="icon-trash"></i>', 'hiddenwin', "title='{$lang->api->deleteStruct}' class='btn'");
if(common::hasPriv('api', 'editStruct')) echo html::a($this->createLink('api', 'editStruct', "libID=$libID&structID=$struct->id"), '<i class="icon-edit"></i>', '', "title='{$lang->api->edit}' class='btn'");
if(common::hasPriv('api', 'deleteStruct')) echo html::a($this->createLink('api', 'deleteStruct', "libID=$libID&structID=$struct->id"), '<i class="icon-trash"></i>', 'hiddenwin', "title='{$lang->api->delete}' class='btn'");
?>
</td>
</tr>
+4 -4
View File
@@ -8,14 +8,14 @@ $lang->backup->restore = 'Restore';
$lang->backup->change = 'Edit Expiration';
$lang->backup->changeAB = 'Edit';
$lang->backup->rmPHPHeader = 'Remove PHP header';
$lang->backup->setting = 'Setting';
$lang->backup->setting = 'Settings';
$lang->backup->settingAction = 'Backup Setting';
$lang->backup->settingAction = 'Backup Settings';
$lang->backup->time = 'Date';
$lang->backup->files = 'Files';
$lang->backup->allCount = 'All Count';
$lang->backup->count = 'Backup Count';
$lang->backup->allCount = 'All Files';
$lang->backup->count = 'Backup Files';
$lang->backup->size = 'Size';
$lang->backup->status = 'Status';
+18 -4
View File
@@ -230,7 +230,7 @@ class block extends control
$commonField = 'common';
if($module == 'project' and $projectID)
{
$project = $this->loadModel('project')->getByID($this->session->project);
$project = $this->loadModel('project')->getByID($projectID);
$commonField = $project->model . 'common';
}
@@ -595,9 +595,15 @@ class block extends control
$this->session->set('storyList', $uri, 'product');
$this->session->set('testtaskList', $uri, 'qa');
$tasks = $this->loadModel('task')->getUserSuspendedTasks($this->app->user->account);
foreach($todos as $key => $todo)
{
if($todo->date == '2030-01-01') unset($todos[$key]);
if($todo->date == '2030-01-01')
{
unset($todos[$key]);
continue;
}
if($todo->type == 'task' and isset($tasks[$todo->idvalue])) unset($todos[$key]);
}
$this->view->todos = $todos;
@@ -886,7 +892,7 @@ class block extends control
}
$today = helper::today();
if(isset($this->config->maxVersion)) $monday = date('Ymd', strtotime($this->loadModel('weekly')->getThisMonday($today)));
$monday = date('Ymd', strtotime($this->loadModel('weekly')->getThisMonday($today)));
$tasks = $this->dao->select("project,
sum(consumed) as totalConsumed,
sum(if(status != 'cancel' and status != 'closed', `left`, 0)) as totalLeft")
@@ -906,7 +912,7 @@ class block extends control
$project->progress = $project->allStories == 0 ? 0 : round($project->doneStories / $project->allStories, 3) * 100;
$project->executions = $this->project->getStats($projectID, 'all', 0, 0, 30, 'id_desc', $pager);
}
elseif($project->model == 'waterfall' and isset($this->config->maxVersion))
elseif($project->model == 'waterfall')
{
$begin = $project->begin;
$weeks = $this->weekly->getWeekPairs($begin);
@@ -1703,6 +1709,7 @@ class block extends control
$objectCountList += array('risk' => 'riskCount', 'issue' => 'issueCount');
}
$tasks = $this->loadModel('task')->getUserSuspendedTasks($this->app->user->account);
foreach($objectCountList as $objectType => $objectCount)
{
if(!isset($hasViewPriv[$objectType])) continue;
@@ -1731,6 +1738,11 @@ class block extends control
unset($objects[$key]);
continue;
}
if($todo->type == 'task' and isset($tasks[$todo->idvalue]))
{
unset($objects[$key]);
continue;
}
$todo->begin = date::formatTime($todo->begin);
$todo->end = date::formatTime($todo->end);
@@ -1741,6 +1753,8 @@ class block extends control
{
$this->app->loadLang('task');
$this->app->loadLang('execution');
$objects = $this->loadModel('task')->getUserTasks($this->app->user->account, 'assignedTo', $limitCount);
}
if($objectType == 'bug') $this->app->loadLang('bug');
-32
View File
@@ -105,48 +105,16 @@ $lang->block->spent = 'Has Been Spent';
$lang->block->budget = 'Budget';
$lang->block->left = 'Residuals';
$lang->block->default['waterfall']['project']['1']['title'] = 'Project Weekly';
$lang->block->default['waterfall']['project']['1']['block'] = 'waterfallreport';
$lang->block->default['waterfall']['project']['1']['source'] = 'project';
$lang->block->default['waterfall']['project']['1']['grid'] = 8;
$lang->block->default['waterfall']['project']['2']['title'] = 'Estimate';
$lang->block->default['waterfall']['project']['2']['block'] = 'waterfallestimate';
$lang->block->default['waterfall']['project']['2']['source'] = 'project';
$lang->block->default['waterfall']['project']['2']['grid'] = 4;
$lang->block->default['waterfall']['project']['3']['title'] = 'Plan Gantt Chart';
$lang->block->default['waterfall']['project']['3']['block'] = 'waterfallgantt';
$lang->block->default['waterfall']['project']['3']['source'] = 'project';
$lang->block->default['waterfall']['project']['3']['grid'] = 8;
$lang->block->default['waterfall']['project']['4']['title'] = 'Progress Chart';
$lang->block->default['waterfall']['project']['4']['block'] = 'waterfallprogress';
$lang->block->default['waterfall']['project']['4']['grid'] = 4;
$lang->block->default['waterfall']['project']['5']['title'] = 'Project Issue';
$lang->block->default['waterfall']['project']['5']['block'] = 'waterfallissue';
$lang->block->default['waterfall']['project']['5']['source'] = 'project';
$lang->block->default['waterfall']['project']['5']['grid'] = 8;
$lang->block->default['waterfall']['project']['5']['params']['type'] = 'all';
$lang->block->default['waterfall']['project']['5']['params']['count'] = '15';
$lang->block->default['waterfall']['project']['5']['params']['orderBy'] = 'id_desc';
$lang->block->default['waterfall']['project']['6']['title'] = 'Dynamic';
$lang->block->default['waterfall']['project']['6']['block'] = 'projectdynamic';
$lang->block->default['waterfall']['project']['6']['grid'] = 4;
$lang->block->default['waterfall']['project']['6']['source'] = 'project';
$lang->block->default['waterfall']['project']['7']['title'] = 'Project Risk';
$lang->block->default['waterfall']['project']['7']['block'] = 'waterfallrisk';
$lang->block->default['waterfall']['project']['7']['source'] = 'project';
$lang->block->default['waterfall']['project']['7']['grid'] = 8;
$lang->block->default['waterfall']['project']['7']['params']['type'] = 'all';
$lang->block->default['waterfall']['project']['7']['params']['count'] = '15';
$lang->block->default['waterfall']['project']['7']['params']['orderBy'] = 'id_desc';
$lang->block->default['scrum']['project']['1']['title'] = 'Project Overview';
$lang->block->default['scrum']['project']['1']['block'] = 'scrumoverview';
$lang->block->default['scrum']['project']['1']['grid'] = 8;
-32
View File
@@ -105,48 +105,16 @@ $lang->block->spent = '已花费';
$lang->block->budget = '预算';
$lang->block->left = '剩余';
$lang->block->default['waterfall']['project']['1']['title'] = '项目周报';
$lang->block->default['waterfall']['project']['1']['block'] = 'waterfallreport';
$lang->block->default['waterfall']['project']['1']['source'] = 'project';
$lang->block->default['waterfall']['project']['1']['grid'] = 8;
$lang->block->default['waterfall']['project']['2']['title'] = '估算';
$lang->block->default['waterfall']['project']['2']['block'] = 'waterfallestimate';
$lang->block->default['waterfall']['project']['2']['source'] = 'project';
$lang->block->default['waterfall']['project']['2']['grid'] = 4;
$lang->block->default['waterfall']['project']['3']['title'] = "项目计划";
$lang->block->default['waterfall']['project']['3']['block'] = 'waterfallgantt';
$lang->block->default['waterfall']['project']['3']['source'] = 'project';
$lang->block->default['waterfall']['project']['3']['grid'] = 8;
$lang->block->default['waterfall']['project']['4']['title'] = '到目前为止项目进展趋势图';
$lang->block->default['waterfall']['project']['4']['block'] = 'waterfallprogress';
$lang->block->default['waterfall']['project']['4']['grid'] = 4;
$lang->block->default['waterfall']['project']['5']['title'] = '项目问题';
$lang->block->default['waterfall']['project']['5']['block'] = 'waterfallissue';
$lang->block->default['waterfall']['project']['5']['source'] = 'project';
$lang->block->default['waterfall']['project']['5']['grid'] = 8;
$lang->block->default['waterfall']['project']['5']['params']['type'] = 'all';
$lang->block->default['waterfall']['project']['5']['params']['count'] = '15';
$lang->block->default['waterfall']['project']['5']['params']['orderBy'] = 'id_desc';
$lang->block->default['waterfall']['project']['6']['title'] = '最新动态';
$lang->block->default['waterfall']['project']['6']['block'] = 'projectdynamic';
$lang->block->default['waterfall']['project']['6']['grid'] = 4;
$lang->block->default['waterfall']['project']['6']['source'] = 'project';
$lang->block->default['waterfall']['project']['7']['title'] = '项目风险';
$lang->block->default['waterfall']['project']['7']['block'] = 'waterfallrisk';
$lang->block->default['waterfall']['project']['7']['source'] = 'project';
$lang->block->default['waterfall']['project']['7']['grid'] = 8;
$lang->block->default['waterfall']['project']['7']['params']['type'] = 'all';
$lang->block->default['waterfall']['project']['7']['params']['count'] = '15';
$lang->block->default['waterfall']['project']['7']['params']['orderBy'] = 'id_desc';
$lang->block->default['scrum']['project']['1']['title'] = '项目概况';
$lang->block->default['scrum']['project']['1']['block'] = 'scrumoverview';
$lang->block->default['scrum']['project']['1']['grid'] = 8;
+13 -1
View File
@@ -166,7 +166,19 @@ class blockModel extends model
{
$data = array();
$data['tasks'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_TASK)->where('assignedTo')->eq($this->app->user->account)->andWhere('deleted')->eq(0)->fetch('count');
$tasks = $this->dao->select('t1.id')->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
->leftJoin(TABLE_PROJECT)->alias('t3')->on('t1.execution=t3.id')
->where('t1.assignedTo')->eq($this->app->user->account)
->andWhere('t2.status')->ne('suspended')
->andWhere('t3.status')->ne('suspended')
->andWhere('t2.type')->eq('project')
->andWhere('t3.type')->in('sprint,stage')
->andWhere('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t3.deleted')->eq(0)
->fetchAll('id');
$data['tasks'] = isset($tasks) ? count($tasks) : 0;
$data['doneTasks'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_TASK)->where('assignedTo')->eq($this->app->user->account)->andWhere('deleted')->eq(0)->andWhere('status')->eq('done')->fetch('count');
$data['bugs'] = (int)$this->dao->select('count(*) AS count')->from(TABLE_BUG)
->where('assignedTo')->eq($this->app->user->account)
+1 -1
View File
@@ -40,7 +40,7 @@ $config->bug->list->exportFields = 'id, product, branch, module, project, execut
$config->bug->list->customCreateFields = 'execution,story,task,pri,severity,os,browser,deadline,mailto,keywords';
$config->bug->list->customBatchCreateFields = 'execution,steps,type,pri,deadline,severity,os,browser,keywords';
$config->bug->list->customBatchEditFields = 'type,severity,pri,productplan,assignedTo,deadline,status,resolvedBy,resolution,os,browser,keywords';
$config->bug->list->customBatchEditFields = 'type,severity,pri,productplan,assignedTo,deadline,resolvedBy,resolution,os,browser,keywords';
$config->bug->custom = new stdclass();
$config->bug->custom->createFields = $config->bug->list->customCreateFields;
+37 -9
View File
@@ -408,15 +408,7 @@ class bug extends control
if($this->app->tab == 'execution')
{
if(!preg_match("/(m=|\/)execution(&f=|-)bug(&|-|\.)?/", $this->session->bugList))
{
$location = $this->session->bugList;
}
else
{
$executionID = $this->post->execution ? $this->post->execution : $output['executionID'];
$location = $this->createLink('execution', 'bug', "executionID=$executionID");
}
$location = $this->session->bugList ? $this->session->bugList : $this->createLink('execution', 'bug', "executionID={$output['executionID']}");
}
elseif($this->app->tab == 'project')
{
@@ -678,6 +670,9 @@ class bug extends control
}
setcookie('bugModule', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
/* If link from no head then reload. */
if(isonlybody()) die(js::reload('parent.parent'));
die(js::locate($this->createLink('bug', 'browse', "productID={$productID}&branch=$branch&browseType=unclosed&param=0&orderBy=id_desc"), 'parent'));
}
@@ -882,6 +877,7 @@ class bug extends control
}
}
}
if(isonlybody()) die(js::reload('parent.parent'));
die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
}
@@ -995,6 +991,11 @@ class bug extends control
*/
public function batchEdit($productID = 0, $branch = 0)
{
if($this->app->tab == 'product')
{
$this->product->setMenu($productID);
}
if($this->post->titles)
{
$allChanges = $this->bug->batchUpdate();
@@ -1257,6 +1258,33 @@ class bug extends control
die(js::locate($this->session->bugList, 'parent'));
}
/**
* Batch change the plan of bug.
*
* @param int $planID
* @access public
* @return void
*/
public function batchChangePlan($planID)
{
if($this->post->bugIDList)
{
$bugIDList = $this->post->bugIDList;
$bugIDList = array_unique($bugIDList);
unset($_POST['bugIDList']);
$allChanges = $this->bug->batchChangePlan($bugIDList, $planID);
if(dao::isError()) die(js::error(dao::getError()));
foreach($allChanges as $bugID => $changes)
{
$this->loadModel('action');
$actionID = $this->action->create('bug', $bugID, 'Edited');
$this->action->logHistory($actionID, $changes);
}
}
$this->loadModel('score')->create('ajax', 'batchOther');
die(js::locate($this->session->bugList, 'parent'));
}
/**
* Batch update assign of bug.
*
+2
View File
@@ -1,3 +1,5 @@
#importLinesModal .modal-dialog {width: 80%;}
.c-id {width: 50px !important;}
.c-branch, .c-module, .c-os {width: 120px;}
.c-execution {width: 130px;}
+1
View File
@@ -46,3 +46,4 @@ html[lang='en'] #deadlineTd .input-group-addon {padding: 5px 18px;}
#osBox {width: 190px;}
#projectBox .required:after {right: 1px;}
#branch_chosen {min-width: 90px;}
#notifyEmailTd .input-group-addon, #deadlineTd .input-group-addon {border-radius: 2px 0px 2px 0px !important;}
+10 -1
View File
@@ -1,7 +1,16 @@
.main-actions {display: none;}
#main {margin-bottom: 40px;}
#main {margin-bottom: 40px; min-width: unset;}
#mainMenu .pull-left>a {display: none;}
#mainMenu .pull-left .divider {display: none;}
#mainMenu .pull-right {display: none;}
#mainContent .col-4 {display: none;}
.modal-dialog {width: 90%;}
#mainMenu {position: fixed; width: 100%; z-index: 999;}
#scrollContent {margin-top: 35px; height: calc(100% - 70px); display: block; overflow: hidden;}
#scrollContent:hover{overflow: overlay;}
html, body, #main, .container { height: 100%;}
body * {font-size: 13px !important; line-height: 1.42857143; color: rgb(51, 51, 51);}
.page-title > .label-id {min-width: 25px; line-height: 13px;}
::-webkit-scrollbar {width: 10px; height: 10px;}
::-webkit-scrollbar-thumb:vertical {box-shadow: inset 1px 1px 0 rgb(0 0 0 / 10%), inset 0 -1px 0 rgb(0 0 0 / 7%); background-color: rgba(0, 0, 0, 0.2); border-radius: 10px; opacity: 0; transition: opacity 0.1s;}
.btn span{line-height: 16px; vertical-align: middle;}
+9 -3
View File
@@ -28,8 +28,14 @@ $(function()
xuanAction += "<a href='" + url + "'" + title + target + btnClass + '>' + action + "</a>";
});
xuanAction += '</div>';
$('body').append(xuanAction);
if(xuanAction != "<div class='xuancard-actions fixed'>")
{
xuanAction += '</div>';
$('body').append(xuanAction);
}
else
{
$('#scrollContent').css('height', 'calc(100% - 36px)');
}
$('.xuancard-actions a.iframe').modalTrigger();
})
+6 -3
View File
@@ -41,13 +41,15 @@ $lang->bug->steps = 'Repro Steps';
$lang->bug->status = 'Status';
$lang->bug->statusAB = 'Status';
$lang->bug->subStatus = 'Sub Status';
$lang->bug->activatedCount = 'Activated Times';
$lang->bug->activatedCount = 'Activation';
$lang->bug->activatedCountAB = 'Active';
$lang->bug->activatedDate = 'ActivatedDate';
$lang->bug->confirmed = 'Confirmed';
$lang->bug->confirmedAB = 'C';
$lang->bug->toTask = 'Convert to Task';
$lang->bug->toStory = 'Convert to Story';
$lang->bug->feedbackBy = 'From Name';
$lang->bug->notifyEmail = 'From Email';
$lang->bug->mailto = 'Mailto';
$lang->bug->openedBy = 'ReportedBy';
$lang->bug->openedByAB = 'Reporter';
@@ -63,8 +65,8 @@ $lang->bug->resolvedByAB = 'ResolvedBy';
$lang->bug->resolution = 'Resolution';
$lang->bug->resolutionAB = 'Resolution';
$lang->bug->resolvedBuild = 'Build';
$lang->bug->resolvedDate = 'Resolved Date';
$lang->bug->resolvedDateAB = 'ResolvedDate';
$lang->bug->resolvedDate = 'Resolved';
$lang->bug->resolvedDateAB = 'Resolved';
$lang->bug->deadline = 'Deadline';
$lang->bug->deadlineAB = 'Deadline';
$lang->bug->plan = 'Plan';
@@ -99,6 +101,7 @@ $lang->bug->edit = 'Edit Bug';
$lang->bug->batchEdit = 'Batch Edit';
$lang->bug->batchChangeModule = 'Batch Edit Modules';
$lang->bug->batchChangeBranch = 'Batch Edit Branches';
$lang->bug->batchChangePlan = 'Batch Edit Plans';
$lang->bug->batchClose = 'Batch Close';
$lang->bug->assignTo = 'Assign';
$lang->bug->assignAction = 'Assign Bug';
+6 -2
View File
@@ -48,6 +48,8 @@ $lang->bug->confirmed = '是否确认';
$lang->bug->confirmedAB = '确认';
$lang->bug->toTask = '转任务';
$lang->bug->toStory = "转{$lang->SRCommon}";
$lang->bug->feedbackBy = '反馈者';
$lang->bug->notifyEmail = '通知邮箱';
$lang->bug->mailto = '抄送给';
$lang->bug->openedBy = '由谁创建';
$lang->bug->openedByAB = '创建者';
@@ -99,6 +101,7 @@ $lang->bug->edit = '编辑Bug';
$lang->bug->batchEdit = '批量编辑';
$lang->bug->batchChangeModule = '批量修改模块';
$lang->bug->batchChangeBranch = '批量修改分支';
$lang->bug->batchChangePlan = '批量修改计划';
$lang->bug->batchClose = '批量关闭';
$lang->bug->assignTo = '指派';
$lang->bug->assignAction = '指派Bug';
@@ -278,8 +281,9 @@ $lang->bug->statusList['active'] = '激活';
$lang->bug->statusList['resolved'] = '已解决';
$lang->bug->statusList['closed'] = '已关闭';
$lang->bug->confirmedList[1] = '是';
$lang->bug->confirmedList[0] = '否';
$lang->bug->confirmedList[''] = '';
$lang->bug->confirmedList[1] = '是';
$lang->bug->confirmedList[0] = '否';
$lang->bug->resolutionList[''] = '';
$lang->bug->resolutionList['bydesign'] = '设计如此';
+49 -2
View File
@@ -85,7 +85,12 @@ class bugModel extends model
/* Use classic mode to replace required project. */
if($this->config->systemMode == 'classic' and strpos($this->config->bug->create->requiredFields, 'project') !== false) $this->config->bug->create->requiredFields = str_replace('project', 'execution', $this->config->bug->create->requiredFields);
$this->dao->insert(TABLE_BUG)->data($bug)->autoCheck()->batchCheck($this->config->bug->create->requiredFields, 'notempty')->exec();
$this->dao->insert(TABLE_BUG)->data($bug)
->autoCheck()
->checkIF($bug->notifyEmail, 'notifyEmail', 'email')
->batchCheck($this->config->bug->create->requiredFields, 'notempty')
->exec();
if(!dao::isError())
{
$bugID = $this->dao->lastInsertID();
@@ -94,6 +99,8 @@ class bugModel extends model
$this->file->saveUpload('bug', $bugID);
empty($bug->case) ? $this->loadModel('score')->create('bug', 'create', $bugID) : $this->loadModel('score')->create('bug', 'createFormCase', $bug->case);
if($bug->execution) $this->loadModel('kanban')->updateLane($bug->execution, 'bug');
/* Callback the callable method to process the related data for object that is transfered to bug. */
if($from && is_callable(array($this, $this->config->bug->fromObjects[$from]['callback']))) call_user_func(array($this, $this->config->bug->fromObjects[$from]['callback']), $bugID);
@@ -249,6 +256,7 @@ class bugModel extends model
$bugID = $this->dao->lastInsertID();
$this->executeHooks($bugID);
if($bug->execution) $this->loadModel('kanban')->updateLane($bug->execution, 'bug');
/* When the bug is created by uploading the image, add the image to the file of the bug. */
$this->loadModel('score')->create('bug', 'create', $bugID);
@@ -661,6 +669,7 @@ class bugModel extends model
->batchCheck($this->config->bug->edit->requiredFields, 'notempty')
->checkIF($bug->resolvedBy, 'resolution', 'notempty')
->checkIF($bug->closedBy, 'resolution', 'notempty')
->checkIF($bug->notifyEmail, 'notifyEmail', 'email')
->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty')
->checkIF($bug->resolution == 'fixed', 'resolvedBuild','notempty')
->where('id')->eq((int)$bugID)
@@ -678,6 +687,8 @@ class bugModel extends model
if(!empty($bug->resolvedBy)) $this->loadModel('score')->create('bug', 'resolve', $bugID);
$this->file->updateObjectID($this->post->uid, $bugID, 'bug');
if($bug->execution and $bug->status != $oldBug->status) $this->loadModel('kanban')->updateLane($bug->execution, 'bug');
return common::createChanges($oldBug, $bug);
}
}
@@ -917,6 +928,7 @@ class bugModel extends model
if(!dao::isError())
{
$this->loadModel('score')->create('bug', 'confirmBug', $oldBug);
if($oldBug->execution) $this->loadModel('kanban')->updateLane($oldBug->execution, 'bug');
return common::createChanges($oldBug, $bug);
}
}
@@ -1029,6 +1041,7 @@ class bugModel extends model
if(!dao::isError())
{
$this->loadModel('score')->create('bug', 'resolve', $oldBug);
if($oldBug->execution) $this->loadModel('kanban')->updateLane($oldBug->execution, 'bug');
/* Link bug to build and release. */
$this->linkBugToBuild($bugID, $bug->resolvedBuild);
@@ -1096,6 +1109,35 @@ class bugModel extends model
return $allChanges;
}
/**
* Batch change the plan of bug.
*
* @param array $bugIDList
* @param int $planID
* @access public
* @return array
*/
public function batchChangePlan($bugIDList, $planID)
{
$now = helper::now();
$allChanges = array();
$oldBugs = $this->getByList($bugIDList);
foreach($bugIDList as $bugID)
{
$oldBug = $oldBugs[$bugID];
if($planID == $oldBug->plan) continue;
$bug = new stdclass();
$bug->lastEditedBy = $this->app->user->account;
$bug->lastEditedDate = $now;
$bug->plan = $planID;
$this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec();
if(!dao::isError()) $allChanges[$bugID] = common::createChanges($oldBug, $bug);
}
return $allChanges;
}
/**
* Batch resolve bugs.
*
@@ -1161,6 +1203,7 @@ class bugModel extends model
$this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec();
$this->executeHooks($bugID);
if($oldBug->execution) $this->loadModel('kanban')->updateLane($oldBug->execution, 'bug');
$changes[$bugID] = common::createChanges($oldBug, $bug);
}
@@ -1218,6 +1261,7 @@ class bugModel extends model
$this->dao->update(TABLE_BUILD)->set('bugs')->eq($build->bugs)->where('id')->eq((int)$solveBuild)->exec();
}
if($oldBug->execution) $this->loadModel('kanban')->updateLane($oldBug->execution, 'bug');
$bug->activatedCount += 1;
return common::createChanges($oldBug, $bug);
}
@@ -1246,6 +1290,7 @@ class bugModel extends model
->get();
$this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec();
if($oldBug->execution) $this->loadModel('kanban')->updateLane($oldBug->execution, 'bug');
return common::createChanges($oldBug, $bug);
}
@@ -1583,7 +1628,9 @@ class bugModel extends model
->beginIF($type == 'noclosed')->andWhere('status')->ne('closed')->fi()
->beginIF($build)->andWhere("CONCAT(',', openedBuild, ',') like '%,$build,%'")->fi()
->beginIF($excludeBugs)->andWhere('id')->notIN($excludeBugs)->fi()
->orderBy($orderBy)->page($pager)->fetchAll();
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
}
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
+1 -3
View File
@@ -59,7 +59,6 @@
<th class='c-plan<?php echo zget($visibleFields, 'productplan', ' hidden') . zget($requiredFields, 'productplan', '', ' required');?>'><?php echo $lang->bug->productplan;?></th>
<th class='c-assigned<?php echo zget($visibleFields, 'assignedTo', ' hidden') . zget($requiredFields, 'assignedTo', '', ' required');?>'><?php echo $lang->bug->assignedTo;?></th>
<th class='c-date<?php echo zget($visibleFields, 'deadline', ' hidden') . zget($requiredFields, 'deadline', '', ' required');?>'><?php echo $lang->bug->deadline;?></th>
<th class='c-status<?php echo zget($visibleFields, 'status', ' hidden')?>'><?php echo $lang->bug->status;?></th>
<th class='c-os<?php echo zget($visibleFields, 'os', ' hidden') . zget($requiredFields, 'os', '', ' required');?>'><?php echo $lang->bug->os;?></th>
<th class='c-browser<?php echo zget($visibleFields, 'browser', ' hidden') . zget($requiredFields, 'browser', '', ' required');?>'><?php echo $lang->bug->browser;?></th>
<th class='c-keywords<?php echo zget($visibleFields, 'keywords', ' hidden') . zget($requiredFields, 'keywords', '', ' required');?>'><?php echo $lang->bug->keywords;?></th>
@@ -119,7 +118,6 @@
<td class='<?php echo zget($visibleFields, 'productplan', ' hidden')?>' style='overflow:visible'><?php echo html::select("plans[$bugID]", $plans, $bug->plan, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'assignedTo', ' hidden')?>' style='overflow:visible'><?php echo html::select("assignedTos[$bugID]", $users, $bug->assignedTo, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'deadline', ' hidden')?>' style='overflow:visible'><?php echo html::input("deadlines[$bugID]", $bug->deadline, "class='form-control form-date'");?></td>
<td <?php echo zget($visibleFields, 'status', "class='hidden'")?>><?php echo html::select("statuses[$bugID]", $statusList, $bug->status, 'class=form-control');?></td>
<td <?php echo zget($visibleFields, 'os', "class='hidden'")?>><?php echo html::select("os[$bugID]", $osList, $bug->os, 'class=form-control');?></td>
<td <?php echo zget($visibleFields, 'browser', "class='hidden'")?>><?php echo html::select("browsers[$bugID]", $browserList, $bug->browser, 'class=form-control');?></td>
<td <?php echo zget($visibleFields, 'keywords', "class='hidden'")?>><?php echo html::input("keywords[$bugID]", $bug->keywords, 'class=form-control');?></td>
@@ -143,7 +141,7 @@
<tr>
<td colspan='<?php echo $branchProduct ? $columns : ($columns - 1);?>' class='text-center form-actions'>
<?php echo html::submitButton();?>
<?php echo html::backButton();?>
<?php echo $this->app->tab == 'product' ? html::a($this->session->bugList, $lang->goback, '', "class='btn btn-back btn-wide'") : html::backButton();?>
</td>
</tr>
</tfoot>
+20
View File
@@ -146,6 +146,26 @@ if($this->app->tab == 'project') js::set('objectID', $projectID);
</div>
</td>
</tr>
<tr>
<th><nobr><?php echo $lang->bug->feedbackBy;?></nobr></th>
<td><?php echo html::input('feedbackBy', '', "class='form-control'");?></td>
<td id='notifyEmailTd'>
<div class='input-group'>
<span class='input-group-addon'><?php echo $lang->bug->notifyEmail?></span>
<span><?php echo html::input('notifyEmail', '', "class='form-control'");?></span>
</div>
</td>
</tr>
<?php else:?>
<td>
<div class='input-group' id='feedback'>
<span class="input-group-addon"><?php echo $lang->bug->feedbackBy?></span>
<?php echo html::input('feedbackBy', '', "class='form-control'");?>
<span class="input-group-addon"><?php echo $lang->bug->notifyEmail?></span>
<?php echo html::input('notifyEmail', '', "class='form-control'");?>
</div>
</td>
</tr>
<?php endif;?>
<?php if($showExecution):?>
<?php $showOS = strpos(",$showFields,", ',os,') !== false;?>
+9 -1
View File
@@ -137,7 +137,7 @@ if($this->app->tab == 'project') js::set('objectID', $bug->project);
</tr>
<tr>
<th><?php echo $lang->bug->status;?></th>
<td><?php echo html::select('status', $lang->bug->statusList, $bug->status, "class='form-control chosen'");?></td>
<td><?php echo zget($lang->bug->statusList, $bug->status);?></td>
</tr>
<tr>
<th><?php echo $lang->bug->confirmed;?></th>
@@ -151,6 +151,14 @@ if($this->app->tab == 'project') js::set('objectID', $bug->project);
<th><?php echo $lang->bug->deadline;?></th>
<td><?php echo html::input('deadline', $bug->deadline, "class='form-control form-date'");?></td>
</tr>
<tr>
<th><?php echo $lang->bug->feedbackBy;?></th>
<td><?php echo html::input('feedbackBy', $bug->feedbackBy, "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->bug->notifyEmail;?></th>
<td><?php echo html::input('notifyEmail', $bug->notifyEmail, "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->bug->os;?></th>
<td><?php echo html::select('os', $lang->bug->osList, $bug->os, "class='form-control chosen'");?></td>
+23 -3
View File
@@ -37,6 +37,9 @@
</div>
<?php endif;?>
</div>
<?php if($this->app->getViewType() == 'xhtml'):?>
<div id="scrollContent">
<?php endif;?>
<div id="mainContent" class="main-row">
<div class="main-col col-8">
<div class="cell">
@@ -65,7 +68,9 @@
?>
</div>
<?php $this->printExtendFields($bug, 'div', "position=left&inForm=0&inCell=1");?>
<div class='cell'><?php include '../../common/view/action.html.php';?></div>
<?php if($this->app->getViewType() != 'xhtml'):?>
<div class="cell"><?php include '../../common/view/action.html.php';?></div>
<?php endif;?>
<?php
$params = "bugID=$bug->id";
$extraParams = "extras=bugID=$bug->id";
@@ -88,7 +93,7 @@
if($this->app->tab != 'product')
{
common::printIcon('bug', 'toStory', "product=$bug->product&branch=$bug->branch&module=0&story=0&execution=0&bugID=$bug->id", $bug, 'button', $lang->icons['story'], '', '', '', "data-app='product'", $lang->bug->toStory);
common::printIcon('bug', 'toStory', "product=$bug->product&branch=$bug->branch&module=0&story=0&execution=0&bugID=$bug->id", $bug, 'button', $lang->icons['story'], '', '', '', "data-app='" . $this->app->tab . "'", $lang->bug->toStory);
common::printIcon('bug', 'createCase', $convertParams, $bug, 'button', 'sitemap');
}
@@ -223,6 +228,14 @@
?>
</td>
</tr>
<tr>
<th><?php echo $lang->bug->feedbackBy;?></th>
<td><?php echo $bug->feedbackBy;?></td>
</tr>
<tr>
<th><?php echo $lang->bug->notifyEmail;?></th>
<td><?php echo $bug->notifyEmail;?></td>
</tr>
<tr>
<th><?php echo $lang->bug->os;?></th>
<td><?php echo $lang->bug->osList[$bug->os];?></td>
@@ -300,7 +313,11 @@
if($bug->openedBuild)
{
$openedBuilds = explode(',', $bug->openedBuild);
foreach($openedBuilds as $openedBuild) isset($builds[$openedBuild]) ? print($builds[$openedBuild] . '<br />') : print($openedBuild . '<br />');
foreach($openedBuilds as $openedBuild)
{
if(!$openedBuild) continue;
isset($builds[$openedBuild]) ? print($builds[$openedBuild] . '<br />') : print($openedBuild . '<br />');
}
}
else
{
@@ -394,6 +411,9 @@
<?php $this->printExtendFields($bug, 'div', "position=right&inForm=0&inCell=1");?>
</div>
</div>
<?php if($this->app->getViewType() == 'xhtml'):?>
</div>
<?php endif;?>
<div id="mainActions" class='main-actions'>
<?php common::printPreAndNext($preAndNext);?>
-1
View File
@@ -54,7 +54,6 @@ class ciModel extends model
*/
public function syncCompileStatus($compile)
{
/* Max retry times is: 3. */
if($compile->times >= 3)
{
$this->dao->update(TABLE_COMPILE)->set('status')->eq('failure')->where('id')->eq($compile->id)->exec();
+4
View File
@@ -4,11 +4,15 @@ $lang->index = new stdclass();
$lang->my = new stdclass();
$lang->todo = new stdclass();
$lang->program = new stdclass();
$lang->programplan = new stdclass();
$lang->product = new stdclass();
$lang->project = new stdclass();
$lang->design = new stdclass();
$lang->stage = new stdclass();
$lang->scrum = new stdclass();
$lang->waterfall = new stdclass();
$lang->execution = new stdclass();
$lang->kanban = new stdclass();
$lang->story = new stdclass();
$lang->release = new stdclass();
$lang->branch = new stdclass();
+73 -62
View File
@@ -45,34 +45,38 @@ $lang->runInfo = "<div class='row'><div class='u-1 a-center' id='debugbar
$lang->agreement = "I have read and agreed to the terms and conditions of <a href='http://zpl.pub/page/zplv12.html' target='_blank'> Z PUBLIC LICENSE 1.2 </a>. <span class='text-danger'>Without authorization, I should not remove, hide or cover any logos/links of ZenTao.</span>";
$lang->designedByAIUX = "<a href='https://api.zentao.net/goto.php?item=aiux' class='link-aiux' target='_blank'><i class='icon icon-aiux'></i> AIUX</a>";
$lang->reset = 'Reset';
$lang->cancel = 'Cancel';
$lang->refresh = 'Refresh';
$lang->edit = 'Edit';
$lang->delete = 'Delete';
$lang->close = 'Close';
$lang->unlink = 'Unlink';
$lang->import = 'Import';
$lang->export = 'Export';
$lang->setFileName = 'File Name';
$lang->submitting = 'Saving...';
$lang->save = 'Save';
$lang->confirm = 'Confirm';
$lang->preview = 'View';
$lang->goback = 'Back';
$lang->goPC = 'PC';
$lang->more = 'More';
$lang->moreLink = 'MORE';
$lang->day = ' Day';
$lang->customConfig = 'Custom Config';
$lang->public = 'Public';
$lang->trunk = 'Trunk';
$lang->sort = 'Order';
$lang->required = 'Required';
$lang->noData = 'No data.';
$lang->fullscreen = 'Fullscreen';
$lang->retrack = 'Retrack';
$lang->whitelist = 'Access whitelist';
$lang->reset = 'Reset';
$lang->cancel = 'Cancel';
$lang->refresh = 'Refresh';
$lang->create = 'Create';
$lang->edit = 'Edit';
$lang->delete = 'Delete';
$lang->close = 'Close';
$lang->unlink = 'Unlink';
$lang->import = 'Import';
$lang->export = 'Export';
$lang->setFileName = 'File Name';
$lang->submitting = 'Saving...';
$lang->save = 'Save';
$lang->confirm = 'Confirm';
$lang->preview = 'View';
$lang->goback = 'Back';
$lang->goPC = 'PC';
$lang->more = 'More';
$lang->moreLink = 'MORE';
$lang->day = ' Day';
$lang->customConfig = 'Custom Config';
$lang->public = 'Public';
$lang->trunk = 'Trunk';
$lang->sort = 'Order';
$lang->required = 'Required';
$lang->noData = 'No data.';
$lang->fullscreen = 'Fullscreen';
$lang->retrack = 'Retrack';
$lang->whitelist = 'Access whitelist';
$lang->globalSetting = 'Global Setting';
$lang->waterfallModel = 'Waterfall';
$lang->all = 'All';
$lang->actions = 'Action';
$lang->restore = 'Reset';
@@ -137,6 +141,7 @@ $lang->program->common = 'Program';
$lang->product->common = 'Product';
$lang->project->common = 'Project';
$lang->execution->common = $config->systemMode == 'new' ? 'Execution' : $lang->executionCommon;
$lang->kanban->common = 'Kanban';
$lang->qa->common = 'QA';
$lang->devops->common = 'DevOps';
$lang->doc->common = 'Doc';
@@ -161,6 +166,13 @@ $lang->dept->common = 'Dept';
$lang->upgrade->common = 'Update';
$lang->program->list = 'Program List';
$lang->program->kanban = 'Program Kanban';
$lang->design->common = 'Design';
$lang->design->HLDS = 'HLDS';
$lang->design->DDS = 'DDS';
$lang->design->DBDS = 'DBDS';
$lang->design->ADS = 'ADS';
$lang->stage->common = 'Stage';
$lang->stage->list = 'Stage List';
$lang->execution->list = "{$lang->executionCommon} List";
$lang->personnel->common = 'Member';
@@ -179,38 +191,37 @@ $lang->score->shortCommon = 'Score';
$lang->testreport->shortCommon = 'Report';
$lang->qa->shortCommon = 'QA';
$lang->dashboard = 'Dashboard';
$lang->contribute = 'Contribute';
$lang->dynamic = 'Dynamic';
$lang->contact = 'Contacts';
$lang->whitelist = 'Whitelist';
$lang->roadmap = 'Roadmap';
$lang->track = 'Track';
$lang->settings = 'Settings';
$lang->overview = 'Overview';
$lang->module = 'Module';
$lang->priv = 'Privilege';
$lang->design = 'Design';
$lang->other = 'Other';
$lang->estimation = 'Estimation';
$lang->issue = 'Issue';
$lang->risk = 'Risk';
$lang->measure = 'Report';
$lang->treeView = 'Tree View';
$lang->groupView = 'Group View';
$lang->kanban = 'Kanban';
$lang->burn = 'Burndown';
$lang->view = 'View';
$lang->intro = 'Introduction';
$lang->indexPage = 'Index';
$lang->model = 'Model';
$lang->redev = 'Develop';
$lang->browser = 'Browser';
$lang->db = 'Database';
$lang->editor = 'Editor';
$lang->timezone = 'Timezone';
$lang->security = 'Security';
$lang->calendar = 'Calendar';
$lang->dashboard = 'Dashboard';
$lang->contribute = 'Contribute';
$lang->dynamic = 'Dynamic';
$lang->contact = 'Contacts';
$lang->whitelist = 'Whitelist';
$lang->roadmap = 'Roadmap';
$lang->track = 'Track';
$lang->settings = 'Settings';
$lang->overview = 'Overview';
$lang->module = 'Module';
$lang->priv = 'Privilege';
$lang->other = 'Other';
$lang->estimation = 'Estimation';
$lang->issue = 'Issue';
$lang->risk = 'Risk';
$lang->measure = 'Report';
$lang->treeView = 'Tree View';
$lang->groupView = 'Group View';
$lang->executionKanban = 'Kanban';
$lang->burn = 'Burndown';
$lang->view = 'View';
$lang->intro = 'Introduction';
$lang->indexPage = 'Index';
$lang->model = 'Model';
$lang->redev = 'Develop';
$lang->browser = 'Browser';
$lang->db = 'Database';
$lang->editor = 'Editor';
$lang->timezone = 'Timezone';
$lang->security = 'Security';
$lang->calendar = 'Calendar';
$lang->my->work = 'Work';
@@ -229,8 +240,8 @@ $lang->doc->api = 'API';
$lang->doc->execution = $lang->execution->common;
$lang->doc->custom = 'Custom';
$lang->doc->wiki = 'WIKI';
$lang->doc->apiDoc = 'Doc';
$lang->doc->apiStruct = 'Struct';
$lang->doc->apiDoc = 'API Docuemnt';
$lang->doc->apiStruct = 'Data Structure';
$lang->product->list = $lang->productCommon . ' List';
$lang->product->kanban = $lang->productCommon . ' Kanban';
+69 -12
View File
@@ -155,7 +155,7 @@ $lang->product->menu = new stdclass();
$lang->product->menu->dashboard = array('link' => "{$lang->dashboard}|product|dashboard|productID=%s");
if($config->URAndSR) $lang->product->menu->requirement = array('link' => "$lang->URCommon|product|browse|productID=%s&branch=&browseType=unclosed&param=0&storyType=requirement", 'alias' => 'batchedit', 'subModule' => 'story');
$lang->product->menu->story = array('link' => "$lang->SRCommon|product|browse|productID=%s", 'alias' => 'batchedit', 'subModule' => 'story');
$lang->product->menu->plan = array('link' => "{$lang->productplan->shortCommon}|productplan|browse|productID=%s", 'subModule' => 'productplan');
$lang->product->menu->plan = array('link' => "{$lang->productplan->shortCommon}|productplan|browse|productID=%s", 'subModule' => 'productplan,bug');
$lang->product->menu->release = array('link' => "{$lang->release->common}|release|browse|productID=%s", 'subModule' => 'release');
$lang->product->menu->roadmap = array('link' => "{$lang->roadmap}|product|roadmap|productID=%s");
if($config->systemMode == 'new') $lang->product->menu->project = array('link' => "{$lang->project->common}|product|project|status=all&productID=%s");
@@ -239,6 +239,52 @@ $lang->scrum->menu->settings['subMenu']->whitelist = array('link' => "{$lang->
$lang->scrum->menu->settings['subMenu']->stakeholder = array('link' => "{$lang->stakeholder->common}|stakeholder|browse|project=%s", 'subModule' => 'stakeholder');
$lang->scrum->menu->settings['subMenu']->group = array('link' => "{$lang->priv}|project|group|project=%s", 'alias' => 'group,manageview,managepriv');
/* Waterfall menu. */
$lang->waterfall->menu = new stdclass();
$lang->waterfall->menu->index = array('link' => "$lang->dashboard|project|index|project=%s");
$lang->waterfall->menu->programplan = array('link' => "{$lang->productplan->shortCommon}|programplan|browse|project=%s&productID=0&type=lists", 'subModule' => 'programplan');
$lang->waterfall->menu->execution = array('link' => "{$lang->stage->common}|project|execution|status=all&projectID=%s");
$lang->waterfall->menu->story = array('link' => "$lang->SRCommon|projectstory|story|project=%s", 'subModule' => 'projectstory,tree', 'exclude' => 'projectstory-track');
$lang->waterfall->menu->design = array('link' => "{$lang->design->common}|design|browse|project=%s");
$lang->waterfall->menu->qa = array('link' => "{$lang->qa->common}|project|bug|projectID=%s", 'subModule' => 'testcase,testtask,bug', 'alias' => 'bug,testtask,testcase');
$lang->waterfall->menu->devops = array('link' => "{$lang->repo->common}|repo|browse|repoID=0&branchID=&objectID=%s", 'subModule' => 'repo');
$lang->waterfall->menu->build = array('link' => "{$lang->build->common}|project|build|project=%s");
$lang->waterfall->menu->release = array('link' => "{$lang->release->common}|projectrelease|browse|project=%s", 'subModule' => 'projectrelease');
$lang->waterfall->menu->dynamic = array('link' => "$lang->dynamic|project|dynamic|project=%s");
$lang->waterfall->menu->settings = $lang->scrum->menu->settings;
$lang->waterfall->dividerMenu = ',programplan,build,dynamic,';
/* Waterfall menu order. */
$lang->waterfall->menuOrder[5] = 'index';
$lang->waterfall->menuOrder[15] = 'programplan';
$lang->waterfall->menuOrder[20] = 'execution';
$lang->waterfall->menuOrder[25] = 'story';
$lang->waterfall->menuOrder[30] = 'design';
$lang->waterfall->menuOrder[35] = 'devops';
$lang->waterfall->menuOrder[55] = 'qa';
$lang->waterfall->menuOrder[60] = 'doc';
$lang->waterfall->menuOrder[65] = 'build';
$lang->waterfall->menuOrder[70] = 'release';
$lang->waterfall->menuOrder[80] = 'dynamic';
$lang->waterfall->menu->doc['subMenu'] = new stdclass();
$lang->waterfall->menu->programplan['subMenu'] = new stdclass();
$lang->waterfall->menu->programplan['subMenu']->lists = array('link' => "{$lang->stage->list}|programplan|browse|projectID=%s&productID=0&type=lists", 'alias' => 'create');
$lang->waterfall->menu->qa['subMenu'] = new stdclass();
$lang->waterfall->menu->qa['subMenu']->bug = array('link' => "{$lang->bug->common}|project|bug|projectID=%s", 'subModule' => 'bug');
$lang->waterfall->menu->qa['subMenu']->testcase = array('link' => "{$lang->testcase->shortCommon}|project|testcase|projectID=%s", 'subModule' => 'testsuite,testcase,caselib,tree');
$lang->waterfall->menu->qa['subMenu']->testtask = array('link' => "{$lang->testtask->common}|project|testtask|projectID=%s", 'subModule' => 'testtask', 'class' => 'dropdown dropdown-hover');
$lang->waterfall->menu->design['subMenu'] = new stdclass();
$lang->waterfall->menu->design['subMenu']->all = array('link' => "$lang->all|design|browse|projectID=%s&productID=0&browseType=all");
$lang->waterfall->menu->design['subMenu']->hlds = array('link' => "{$lang->design->HLDS}|design|browse|projectID=%s&productID=0&browseType=HLDS");
$lang->waterfall->menu->design['subMenu']->dds = array('link' => "{$lang->design->DDS}|design|browse|projectID=%s&productID=0&browseType=DDS");
$lang->waterfall->menu->design['subMenu']->dbds = array('link' => "{$lang->design->DBDS}|design|browse|projectID=%s&productID=0&browseType=DBDS");
$lang->waterfall->menu->design['subMenu']->ads = array('link' => "{$lang->design->ADS}|design|browse|projectID=%s&productID=0&browseType=ADS");
$lang->waterfall->menu->design['subMenu']->bysearch = array('link' => '<a href="javascript:;" class="querybox-toggle"><i class="icon-search icon"></i> ' . $lang->searchAB . '</a>');
/* Execution menu. */
$lang->execution->homeMenu = new stdclass();
@@ -247,7 +293,7 @@ if($config->systemMode == 'new') $lang->execution->homeMenu->executionkanban = a
$lang->execution->menu = new stdclass();
$lang->execution->menu->task = array('link' => "{$lang->task->common}|execution|task|executionID=%s", 'subModule' => 'task,tree', 'alias' => 'importtask,importbug');
$lang->execution->menu->kanban = array('link' => "$lang->kanban|execution|kanban|executionID=%s");
$lang->execution->menu->kanban = array('link' => "$lang->executionKanban|execution|kanban|executionID=%s");
$lang->execution->menu->burn = array('link' => "$lang->burn|execution|burn|executionID=%s");
$lang->execution->menu->view = array('link' => "$lang->view|execution|grouptask|executionID=%s", 'alias' => 'grouptask,tree,taskeffort,gantt,calendar,relation,maintainrelation');
$lang->execution->menu->story = array('link' => "$lang->SRCommon|execution|story|executionID=%s", 'subModule' => 'story', 'alias' => 'batchcreate,linkstory,storykanban');
@@ -415,13 +461,24 @@ $lang->company->menuOrder[30] = 'addUser';
$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->model = array('link' => "$lang->model|custom|browsestoryconcept|", 'subModule' => 'holiday');
$lang->admin->menu->model = array('link' => "$lang->model|custom|browsestoryconcept|", 'class' => 'dropdown dropdown-hover', 'exclude' => 'custom-index,custom-set,custom-product,custom-execution,custom-required,custom-flow,custom-score,custom-feedback,custom-timezone,custom-mode');
$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');
$lang->admin->menu->system = array('link' => "{$lang->admin->system}|backup|index", 'subModule' => 'cron,backup,action,admin,search', 'exclude' => 'admin-index,admin-xuanxuan,admin-register,admin-ztcompany');
$lang->admin->menu->model['dropMenu'] = new stdclass();
$lang->admin->menu->model['dropMenu']->allModel = array('link' => "{$lang->globalSetting}|custom|browsestoryconcept|", 'subModule' => 'measurement,report,sqlbuilder,subject,custom,meetingroom,baseline');
$lang->admin->menu->model['dropMenu']->waterfall = array('link' => "{$lang->waterfallModel}|stage|setType|", 'subModule' => 'stage,auditcl,cmcl,process,activity,zoutput,classify,reviewcl,reviewsetting');
$lang->admin->menu->allModel['subMenu'] = new stdclass();
$lang->admin->menu->allModel['subMenu']->storyConcept = array('link' => "{$lang->storyConcept}|custom|browsestoryconcept|");
$lang->admin->menu->allModel['menuOrder'][5] = 'storyConcept';
$lang->admin->menu->waterfall['subMenu'] = new stdclass();
$lang->admin->menu->waterfall['subMenu']->stage = array('link' => '阶段|stage|setType|', 'subModule' => 'stage');
/* Admin menu order. */
$lang->admin->menuOrder[5] = 'index';
$lang->admin->menuOrder[10] = 'company';
@@ -432,11 +489,6 @@ $lang->admin->menuOrder[30] = 'extension';
$lang->admin->menuOrder[35] = 'dev';
$lang->admin->menuOrder[40] = 'system';
$lang->admin->menu->model['subMenu'] = new stdclass();
$lang->admin->menu->model['subMenu']->storyConcept = array('link' => "{$lang->storyConcept}|custom|browsestoryconcept|");
$lang->admin->menu->model['menuOrder'][5] = 'storyConcept';
$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');
@@ -507,6 +559,8 @@ $lang->navGroup->story = 'product';
$lang->navGroup->project = 'project';
$lang->navGroup->deploy = 'project';
$lang->navGroup->programplan = 'project';
$lang->navGroup->design = 'project';
$lang->navGroup->stakeholder = 'project';
$lang->navGroup->projectbuild = 'project';
@@ -522,10 +576,13 @@ $lang->navGroup->build = 'project';
$lang->navGroup->measrecord = 'project';
$lang->navGroup->milestone = 'project';
$lang->navGroup->execution = 'execution';
$lang->navGroup->task = 'execution';
$lang->navGroup->build = 'execution';
$lang->navGroup->team = 'execution';
$lang->navGroup->kanban = 'execution';
$lang->navGroup->execution = 'execution';
$lang->navGroup->task = 'execution';
$lang->navGroup->build = 'execution';
$lang->navGroup->team = 'execution';
$lang->navGroup->kanbancolumn = 'execution';
$lang->navGroup->kanbanlane = 'execution';
$lang->navGroup->doc = 'doc';
$lang->navGroup->doclib = 'doc';
+71 -60
View File
@@ -45,34 +45,38 @@ $lang->runInfo = "<div class='row'><div class='u-1 a-center' id='debugbar
$lang->agreement = "已阅读并同意<a href='http://zpl.pub/page/zplv12.html' target='_blank'>《Z PUBLIC LICENSE授权协议1.2》</a>。<span class='text-danger'>未经许可,不得去除、隐藏或遮掩禅道软件的任何标志及链接。</span>";
$lang->designedByAIUX = "<a href='https://api.zentao.net/goto.php?item=aiux' class='link-aiux' target='_blank'><i class='icon icon-aiux'></i> 艾体验设计</a>";
$lang->reset = '重填';
$lang->cancel = '取消';
$lang->refresh = '刷新';
$lang->edit = '编辑';
$lang->delete = '删除';
$lang->close = '关闭';
$lang->unlink = '移除';
$lang->import = '导入';
$lang->export = '导出';
$lang->setFileName = '文件名:';
$lang->submitting = '稍候...';
$lang->save = '保存';
$lang->confirm = '确认';
$lang->preview = '查看';
$lang->goback = '返回';
$lang->goPC = 'PC版';
$lang->more = '更多';
$lang->moreLink = 'More';
$lang->day = '天';
$lang->customConfig = '自定义';
$lang->public = '公共';
$lang->trunk = '主干';
$lang->sort = '排序';
$lang->required = '必填';
$lang->noData = '暂无';
$lang->fullscreen = '全屏';
$lang->retrack = '收起';
$lang->whitelist = '访问白名单';
$lang->reset = '重填';
$lang->cancel = '取消';
$lang->refresh = '刷新';
$lang->create = '新建';
$lang->edit = '编辑';
$lang->delete = '删除';
$lang->close = '关闭';
$lang->unlink = '移除';
$lang->import = '导入';
$lang->export = '导出';
$lang->setFileName = '文件名:';
$lang->submitting = '稍候...';
$lang->save = '保存';
$lang->confirm = '确认';
$lang->preview = '查看';
$lang->goback = '返回';
$lang->goPC = 'PC版';
$lang->more = '更多';
$lang->moreLink = 'More';
$lang->day = '天';
$lang->customConfig = '自定义';
$lang->public = '公共';
$lang->trunk = '主干';
$lang->sort = '排序';
$lang->required = '必填';
$lang->noData = '暂无';
$lang->fullscreen = '全屏';
$lang->retrack = '收起';
$lang->whitelist = '访问白名单';
$lang->globalSetting = '全局设置';
$lang->waterfallModel = '瀑布模型';
$lang->all = '所有';
$lang->actions = '操作';
$lang->restore = '恢复默认';
@@ -141,6 +145,7 @@ $lang->program->common = '项目集';
$lang->product->common = '产品';
$lang->project->common = '项目';
$lang->execution->common = $config->systemMode == 'new' ? '执行' : $lang->executionCommon;
$lang->kanban->common = '看板';
$lang->qa->common = '测试';
$lang->devops->common = 'DevOps';
$lang->doc->common = '文档';
@@ -165,6 +170,13 @@ $lang->dept->common = '部门';
$lang->upgrade->common = '升级';
$lang->program->list = '项目集列表';
$lang->program->kanban = '项目集看板';
$lang->design->common = '设计';
$lang->design->HLDS = '概要设计';
$lang->design->DDS = '详细设计';
$lang->design->DBDS = '数据库设计';
$lang->design->ADS = '接口设计';
$lang->stage->common = '阶段';
$lang->stage->list = '阶段列表';
$lang->execution->list = "{$lang->executionCommon}列表";
$lang->personnel->common = '人员';
@@ -183,38 +195,37 @@ $lang->score->shortCommon = '积分';
$lang->testreport->shortCommon = '报告';
$lang->qa->shortCommon = 'QA';
$lang->dashboard = '仪表盘';
$lang->contribute = '贡献';
$lang->dynamic = '动态';
$lang->contact = '联系人';
$lang->whitelist = '白名单';
$lang->roadmap = '路线图';
$lang->track = '矩阵';
$lang->settings = '设置';
$lang->overview = '概况';
$lang->module = '模块';
$lang->priv = '权限';
$lang->design = '设计';
$lang->other = '其他';
$lang->estimation = '估算';
$lang->issue = '问题';
$lang->risk = '风险';
$lang->measure = '度量';
$lang->treeView = '树状图';
$lang->groupView = '分组视图';
$lang->kanban = '看板';
$lang->burn = '燃尽图';
$lang->view = '视图';
$lang->intro = '介绍';
$lang->indexPage = '首页';
$lang->model = '模型';
$lang->redev = '二次开发';
$lang->browser = '浏览器';
$lang->db = '数据库';
$lang->editor = '编辑器';
$lang->timezone = '时区';
$lang->security = '安全';
$lang->calendar = '日程';
$lang->dashboard = '仪表盘';
$lang->contribute = '贡献';
$lang->dynamic = '动态';
$lang->contact = '联系人';
$lang->whitelist = '白名单';
$lang->roadmap = '路线图';
$lang->track = '矩阵';
$lang->settings = '设置';
$lang->overview = '概况';
$lang->module = '模块';
$lang->priv = '权限';
$lang->other = '其他';
$lang->estimation = '估算';
$lang->issue = '问题';
$lang->risk = '风险';
$lang->measure = '度量';
$lang->treeView = '树状图';
$lang->groupView = '分组视图';
$lang->executionKanban = '看板';
$lang->burn = '燃尽图';
$lang->view = '视图';
$lang->intro = '介绍';
$lang->indexPage = '首页';
$lang->model = '模型';
$lang->redev = '二次开发';
$lang->browser = '浏览器';
$lang->db = '数据库';
$lang->editor = '编辑器';
$lang->timezone = '时区';
$lang->security = '安全';
$lang->calendar = '日程';
$lang->my->work = '待处理';
+31 -31
View File
@@ -179,37 +179,37 @@ $lang->score->shortCommon = '積分';
$lang->testreport->shortCommon = '報告';
$lang->qa->shortCommon = 'QA';
$lang->dashboard = '儀表盤';
$lang->contribute = '貢獻';
$lang->dynamic = '動態';
$lang->contact = '聯繫人';
$lang->whitelist = '白名單';
$lang->roadmap = '路線圖';
$lang->track = '矩陣';
$lang->settings = '設置';
$lang->overview = '概況';
$lang->module = '模組';
$lang->priv = '權限';
$lang->design = '設計';
$lang->other = '其他';
$lang->estimation = '估算';
$lang->issue = '問題';
$lang->risk = '風險';
$lang->measure = '度量';
$lang->treeView = '樹狀圖';
$lang->groupView = '分組視圖';
$lang->kanban = '看板';
$lang->burn = '燃盡圖';
$lang->view = '視圖';
$lang->intro = '介紹';
$lang->indexPage = '首頁';
$lang->model = '模型';
$lang->redev = '二次開發';
$lang->browser = '瀏覽器';
$lang->db = '資料庫';
$lang->editor = '編輯器';
$lang->timezone = '時區';
$lang->security = '安全';
$lang->dashboard = '儀表盤';
$lang->contribute = '貢獻';
$lang->dynamic = '動態';
$lang->contact = '聯繫人';
$lang->whitelist = '白名單';
$lang->roadmap = '路線圖';
$lang->track = '矩陣';
$lang->settings = '設置';
$lang->overview = '概況';
$lang->module = '模組';
$lang->priv = '權限';
$lang->design = '設計';
$lang->other = '其他';
$lang->estimation = '估算';
$lang->issue = '問題';
$lang->risk = '風險';
$lang->measure = '度量';
$lang->treeView = '樹狀圖';
$lang->groupView = '分組視圖';
$lang->executionKanban = '看板';
$lang->burn = '燃盡圖';
$lang->view = '視圖';
$lang->intro = '介紹';
$lang->indexPage = '首頁';
$lang->model = '模型';
$lang->redev = '二次開發';
$lang->browser = '瀏覽器';
$lang->db = '資料庫';
$lang->editor = '編輯器';
$lang->timezone = '時區';
$lang->security = '安全';
$lang->calendar = '日程';
$lang->my->work = '待處理';
+3
View File
@@ -847,6 +847,9 @@ class commonModel extends model
$linkPart = explode('|', $menu['link']);
if(!isset($linkPart[2])) continue;
$method = $linkPart[2];
if($currentModule == 'report' and $method == 'annualData') continue; // Skip some pages that do not require permissions.
if(common::hasPriv($currentModule, $method))
{
$display = true;
+1 -1
View File
@@ -25,7 +25,7 @@ include 'chosen.html.php';
</div>
</div>
</div>
<?php if(isset($lang->{$app->tab}->menu->$activeMenu) and isset($lang->{$app->tab}->menu->{$activeMenu}['subMenu'])):?>
<?php if(isset($lang->{$app->tab}->menu->$activeMenu) and is_array($lang->{$app->tab}->menu->$activeMenu) and isset($lang->{$app->tab}->menu->{$activeMenu}['subMenu'])):?>
<div id='subHeader'>
<div class='container'>
<div id="pageNav" class='btn-toolbar'><?php if(isset($lang->modulePageNav)) echo $lang->modulePageNav;?></div>
+1
View File
@@ -71,6 +71,7 @@ if($extHookFiles) foreach($extHookFiles as $extHookFile) include $extHookFile;
?>
</head>
<?php $singleClass = $this->app->getViewType() == 'xhtml' ? 'allow-self-open' : '';?>
<?php if(isset($pageBodyClass)) $singleClass = $singleClass . ' ' . $pageBodyClass; ?>
<?php if($this->moduleName == 'index' && $this->methodName == 'index'): ?>
<body class='menu-<?php echo $this->cookie->hideMenu ? 'hide' : 'show'; ?> <?php echo $singleClass;?>'>
<?php else: ?>
+55 -19
View File
@@ -5,7 +5,7 @@
#kanbanList .panel-heading {padding: 10px;}
#kanbanList .panel-body {padding: 0 10px 10px;}
#kanbanList .kanban {min-height: 120px; overflow: visible;}
#kanbanList .kanban-item {margin-top: 0; border: 1px solid #ebebeb; border-radius: 2px;}
#kanbanList .kanban-item {margin-top: 0; border-radius: 2px;}
#kanbanList .kanban-item:hover {border: 1px solid #ccc;}
#kanbanList .kanban-item + .kanban-item {margin-top: 10px;}
#kanbanList .kanban-lane-items {padding: 10px; min-height: 38px;}
@@ -43,9 +43,13 @@
#kanbanList .kanban-header-col[data-type="doingProject"] + .kanban-header-col[data-type="doingExecution"] {padding: 38px 10px 0;}
#kanbanList .kanban-header-col[data-type="doingProject"]:after {content: attr(data-span-text); display: block; position: absolute; z-index: 10; left: 0; right: -100%; right: calc(-100% - 2px); top: 0; line-height: 36px; text-align: center; font-weight: bold; border-bottom: 2px solid #fff; background-color: #ededed;}
#kanbanList .kanban-col[data-type="unclosedProduct"] .kanban-lane-items {height: 100%; display: flex; flex-direction: column; justify-content: center;}
#kanbanList .kanban-col[data-type="unclosedProduct"] .kanban-item {background-color: transparent; border: none; padding: 0; text-align: center;}
#kanbanList .kanban-item.kanban-item-span,
#kanbanList .kanban-col[data-type="unclosedProduct"] .kanban-item {background-color: transparent; border: none; padding: 0; text-align: center; box-shadow: none!important;}
#kanbanList .kanban-item.kanban-item-span:hover,
#kanbanList .kanban-col[data-type="unclosedProduct"] .kanban-item:hover {box-shadow: none;}
#kanbanList .kanban-item.kanban-item-span > .title,
#kanbanList .kanban-col[data-type="unclosedProduct"] .kanban-item > .title {white-space: normal;}
#kanbanList .kanban-col[data-type="normalRelease"] .kanban-item > .title {display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center; height: 38px;}
#kanbanList .kanban-col[data-type="normalRelease"] .kanban-item > .title > .text {display: block; white-space: nowrap; text-overflow: clip; overflow: hidden;}
#kanbanList .kanban-col[data-type="normalRelease"] .kanban-item > .title.has-icon > .text {margin-right: 5px; max-width: calc(100% - 20px);}
@@ -55,8 +59,7 @@
#kanbanList .kanban-affixed .kanban-header-col[data-type="doingProject"]:after {background-color: #606060;}
/* Show project and execution in one row */
#kanbanList .kanban-lane-col[data-type="doingProject"] {box-shadow: 2px 0 0 #fff;}
#kanbanList .kanban-lane-col[data-type="doingProject"] + .kanban-lane-col {border-left: none;}
#kanbanList .kanban-lane-col[data-type="doingProject"] + .kanban-lane-col {border-left: none; box-shadow: inset 2px 0 0 #fff;}
#kanbanList .kanban-lane-col[data-type="doingProject"] > .kanban-lane-items {padding: 0; overflow: visible; max-height: none!important;}
#kanbanList .project-row {position: relative; width: 200%; width: calc(200% + 2px);}
#kanbanList .project-row + .project-row {border-top: 2px solid #fff;}
@@ -84,6 +87,24 @@ function isEarlierThanToday(date)
return $.zui.createDate(date).getTime() < window.todayBegin;
}
/**
* Render normal text span item
* @param {Object} item Product item object
* @param {JQuery} $item Kanban item element
* @param {Object} col Column object
* @returns {JQuery} $item Kanban item element
*/
function renderSpanItem(item, $item)
{
var $title = $item.find('.title');
if(!$title.length)
{
$title = $('<div class="title" />').appendTo($item);
}
$title.text(item.name).attr('title', item.name);
return $item.addClass('kanban-item-span');
}
/**
* Render product item
* @param {Object} item Product item object
@@ -210,6 +231,11 @@ function renderExecutionItem(item, $item)
}
$title.text(item.name).attr('title', item.name);
if(window.statusColorList && window.statusColorList[item.status])
{
$item.css('borderLeftColor', window.statusColorList[item.status]);
}
var progress = item.progress || (item.hours && !Array.isArray(item.hours) ? Math.round(item.hours.progress) : undefined);
if(progress === undefined && window.hourList)
{
@@ -301,6 +327,8 @@ function renderDoingProjectItem(item, $item)
/** All build-in columns renderers */
if(!window.columnRenderers) window.columnRenderers =
{
span: renderSpanItem,
execution: renderExecutionItem,
unclosedProduct: renderProductItem,
unexpiredPlan: renderPlanItem,
waitProject: renderProjectItem,
@@ -331,9 +359,10 @@ function addColumnRenderer(columnType, renderer)
* @param {Object} col Column object
* @returns {JQuery} $item Kanban item element
*/
function renderKanbanItem(item, $item, col)
function renderKanbanItem(item, $item, col, lane, kanban)
{
var renderer = window.columnRenderers[col.type];
var columnRenderers = window.columnRenderers;
var renderer = columnRenderers[col.cardType] || columnRenderers[col.type] || columnRenderers[lane.defaultCardType || kanban.defaultCardType];
if(renderer) return renderer(item, $item, col);
return $item;
}
@@ -365,18 +394,17 @@ function affixKanbanHeader($kanbanBoard, affixed)
*/
function updateKanbanAffixState()
{
var $boards = $('.kanban-board');
var $boards = $('.kanban-board');
var $lastAffixedBoard = $boards.filter('.kanban-affixed');
var containerTop = window.kanbanAffixContainer ? $(window.kanbanAffixContainer)[0].getBoundingClientRect().top : 0;
var $currentAffixedBoard;
var currentOffsetTop = 0;
var scrollTop = $(window).scrollTop();
$('.kanban-board').each(function()
{
var $board = $(this);
var offsetTop = $board.offset().top;
if(scrollTop >= offsetTop && offsetTop > currentOffsetTop && scrollTop < (offsetTop + $board.outerHeight() - 72))
var bounds = $board[0].getBoundingClientRect();
if(bounds.top < containerTop && bounds.bottom > (containerTop))
{
currentOffsetTop = offsetTop;
$currentAffixedBoard = $board;
}
});
@@ -397,20 +425,24 @@ $.extend($.fn.kanban.Constructor.DEFAULTS,
{
readonly: true,
maxColHeight: 260,
/* laneItemsClass: 'scrollbar-hover', */ // only show scrollbar on mouse hover
itemRender: renderKanbanItem,
useFlex: false,
showCount: false,
showCount: true,
showZeroCount: true,
onRenderHeaderCol: function($col, col)
{
if(col.type === 'doingProject') $col.attr('data-span-text', doingText);
if(col.type === 'doingProject' && window.doingText) $col.attr('data-span-text', window.doingText);
},
onRenderKanban: function($kanban, kanbanData)
{
$kanban.find('.kanban-lane-name').each(function(index)
$kanban.find('.kanban-lane').each(function(index)
{
var $lane = $(this);
if ($lane.data('lane').color) return;
var $laneName = $lane.find('.kanban-lane-name');
var color = kanbanColorList[index % kanbanColorList.length];
$(this).css('background-color', color);
$laneName.css('background-color', color);
});
/* Update project count and execution count */
@@ -422,9 +454,13 @@ $.extend($.fn.kanban.Constructor.DEFAULTS,
doingProjectCount = $doingProjectItems.find('.project-item').length;
doingExecutionCount = $doingProjectItems.find('.execution-item').length;
}
$kanban.find('.kanban-header-col[data-type="doingProject"] > .title > .count').text(doingProjectCount || 0);
$kanban.find('.kanban-header-col[data-type="doingExecution"] > .title > .count').text(doingExecutionCount || 0);
},
onCreate: function(kanban)
{
kanban.$.on('scroll', updateKanbanAffixState);
updateKanbanAffixState();
}
});
@@ -438,7 +474,7 @@ $(function()
updateKanbanAffixState();
updateTimer = null;
};
$(window).on('scroll resize', function(e)
$(window.kanbanAffixContainer || window).on('scroll resize', function(e)
{
if(updateTimer)
{
-2
View File
@@ -27,7 +27,5 @@ function submitForm(type)
$('.modal-body #insert').val(type == 'insert' ? 1 : 0);
$('#importNoticeModal .form-actions .btn').addClass('disabled');
$("button[data-target='#importNoticeModal']").closest('form').submit();
setTimeout(function(){$('#importNoticeModal .form-actions .btn').removeClass('disabled');}, 1000);
}
</script>
+5 -4
View File
@@ -167,10 +167,11 @@ class company extends control
* @param int $productID
* @param int $projectID
* @param int $executionID
* @param string $orderBy date_deac|date_asc
* @access public
* @return void
*/
public function dynamic($browseType = 'today', $param = '', $recTotal = 0, $date = '', $direction = 'next', $userID = '', $productID = 0, $projectID = 0, $executionID = 0)
public function dynamic($browseType = 'today', $param = '', $recTotal = 0, $date = '', $direction = 'next', $userID = '', $productID = 0, $projectID = 0, $executionID = 0, $orderBy = 'date_desc')
{
$this->company->setMenu();
$this->app->loadLang('user');
@@ -203,8 +204,8 @@ class company extends control
$pager = new pager($recTotal, $recPerPage = 50, $pageID = 1);
/* Append id for secend sort. */
$orderBy = $direction == 'next' ? 'date_desc' : 'date_asc';
$sort = $this->loadModel('common')->appendOrder($orderBy);
$order = $direction == 'next' ? 'date_desc' : 'date_asc';
$sort = $this->loadModel('common')->appendOrder($order);
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
$date = empty($date) ? '' : date('Y-m-d', $date);
@@ -289,7 +290,7 @@ class company extends control
$this->view->userID = $userID;
$this->view->param = $param;
$this->view->browseType = $browseType;
$this->view->dateGroups = $this->action->buildDateGroup($actions, $direction, $browseType);
$this->view->dateGroups = $this->action->buildDateGroup($actions, $direction, $browseType, $orderBy);
$this->view->direction = $direction;
$this->display();
}
+2 -1
View File
@@ -18,5 +18,6 @@
.dynamic.collapsed .timeline > li + li {display: none;}
.dynamic.collapsed .dynamic-btn > .icon:before {content: '\f0d8';}
.c-user, .c-project, .c-product, .c-execution {width: 150px !important; overflow: unset;}
.c-project, .c-product, .c-execution {width: 140px !important; overflow: unset;}
.c-user,.c-order {width: 100px !important; overflow: unset;}
.c-date {width: 200px;}
+3 -2
View File
@@ -1,11 +1,12 @@
$('#account, #product, #project, #execution').change(function()
$('#account, #product, #project, #execution, #orderBy').change(function()
{
var userID = $('#account').val();
var productID = $('#product').val();
var projectID = systemMode == 'new' ? $('#project').val() : 0;
var executionID = $('#execution').val();
var orderBy = $('#orderBy').val();
browseType = browseType == 'bysearch' ? 'all' : browseType;
link = createLink('company', 'dynamic', 'browseType=' + browseType + '&param=&recTotal=0&date=&direction=next&userID=' + userID + '&productID=' + productID + '&projectID=' + projectID + '&executionID=' + executionID);
link = createLink('company', 'dynamic', 'browseType=' + browseType + '&param=&recTotal=0&date=&direction=next&userID=' + userID + '&productID=' + productID + '&projectID=' + projectID + '&executionID=' + executionID + '&orderBy=' + orderBy);
location.href = link;
})
+3
View File
@@ -37,3 +37,6 @@ $lang->company->user = 'User';
$lang->company->guestOptions[0] = 'Deny';
$lang->company->guestOptions[1] = 'Allow';
$lang->company->order['date_desc'] = 'Descending';
$lang->company->order['date_asc'] = 'Ascending';
+3
View File
@@ -37,3 +37,6 @@ $lang->company->user = '用户';
$lang->company->guestOptions[0] = '不允许';
$lang->company->guestOptions[1] = '允许';
$lang->company->order['date_desc'] = '倒序排列';
$lang->company->order['date_asc'] = '正序排列';
+4 -4
View File
@@ -24,7 +24,7 @@
$active = 'btn-active-text';
$label .= " <span class='label label-light label-badge'>{$pager->recTotal}</span>";
}
echo html::a(inlink('dynamic', "browseType=$period&param=&recTotal=0&date=&direction=next&userID=$userID&productID=$productID&projectID=$projectID&executionID=$executionID"), $label, '', "class='btn btn-link $active' id='{$period}'")
echo html::a(inlink('dynamic', "browseType=$period&param=&recTotal=0&date=&direction=next&userID=$userID&productID=$productID&projectID=$projectID&executionID=$executionID&orderBy=$orderBy"), $label, '', "class='btn btn-link $active' id='{$period}'")
?>
<?php endforeach;?>
<div class="input-control space c-user"><?php echo html::select('account', $userIdPairs, $userID, 'class="form-control chosen" data-max_drop_width="215"');?></div>
@@ -33,6 +33,7 @@
<div class="input-control space c-project"><?php echo html::select('project', $projects, $projectID, 'class="form-control chosen" data-max_drop_width="215"');?></div>
<?php endif;?>
<div class="input-control space c-execution"><?php echo html::select('execution', $executions, $executionID, 'class="form-control chosen" data-max_drop_width="215"'); ?></div>
<div class="input-control space c-order"><?php echo html::select('orderBy', $lang->company->order, $orderBy, 'class="form-control chosen" data-max_drop_width="215"'); ?></div>
<a class="btn btn-link querybox-toggle" id="bysearchTab"><i class="icon icon-search muted"></i> <?php echo $lang->action->dynamic->search;?></a>
</div>
</div>
@@ -52,7 +53,6 @@
<button type="button" class="btn btn-info btn-icon btn-sm dynamic-btn"><i class="icon icon-caret-down"></i></button>
</div>
<ul class="timeline timeline-tag-left <?php if($browseType == 'all') echo 'margin-l-50px';?>">
<?php if($direction == 'next') $actions = array_reverse($actions);?>
<?php foreach($actions as $i => $action):?>
<?php if(empty($firstAction)) $firstAction = $action;?>
<li <?php if($action->major) echo "class='active'";?>>
@@ -96,8 +96,8 @@ $firstDate = date('Y-m-d', strtotime($firstAction->originalDate) + 24 * 3600);
$lastDate = substr($action->originalDate, 0, 10);
$hasPre = $this->action->hasPreOrNext($firstDate, 'pre');
$hasNext = $this->action->hasPreOrNext($lastDate, 'next');
$preLink = $hasPre ? inlink('dynamic', "browseType=$browseType&param=$param&recTotal={$pager->recTotal}&date=" . strtotime($firstDate) . '&direction=pre') : 'javascript:;';
$nextLink = $hasNext ? inlink('dynamic', "browseType=$browseType&param=$param&recTotal={$pager->recTotal}&date=" . strtotime($lastDate) . '&direction=next') : 'javascript:;';
$preLink = $hasPre ? inlink('dynamic', "browseType=$browseType&param=$param&recTotal={$pager->recTotal}&date=" . strtotime($firstDate) . "&direction=pre&userID=$userID&productID=$productID&projectID=$projectID&executionID=$executionID&orderBy=$orderBy") : 'javascript:;';
$nextLink = $hasNext ? inlink('dynamic', "browseType=$browseType&param=$param&recTotal={$pager->recTotal}&date=" . strtotime($lastDate) . "&direction=next&userID=$userID&productID=$productID&projectID=$projectID&executionID=$executionID&orderBy=$orderBy") : 'javascript:;';
?>
<?php if($hasPre or $hasNext):?>
<div id="mainActions" class='main-actions'>
+4 -4
View File
@@ -121,7 +121,7 @@ class compileModel extends model
*/
public function exec($compile)
{
$job = $this->dao->select('t1.id,t1.name,t1.repo,t1.engine,t1.pipeline,t2.name as jenkinsName,t2.url,t2.account,t2.token,t2.password')
$job = $this->dao->select('t1.id,t1.name,t1.repo,t1.pipeline,t2.name as jenkinsName,t2.url,t2.account,t2.token,t2.password')
->from(TABLE_JOB)->alias('t1')
->leftJoin(TABLE_PIPELINE)->alias('t2')->on('t1.server=t2.id')
->where('t1.id')->eq($compile->job)
@@ -134,7 +134,7 @@ class compileModel extends model
if($job->triggerType == 'tag')
{
$lastTag = $this->loadModel('job')->getLastTagByRepo($repo);
$lastTag = $this->getLastTagByRepo($repo);
if($lastTag)
{
$job->lastTag = $lastTag;
@@ -150,8 +150,8 @@ class compileModel extends model
$this->dao->update(TABLE_COMPILE)->data($compile)->where('id')->eq($compileID)->exec();
$this->dao->update(TABLE_JOB)
->set('lastStatus')->eq($compile->status)
->set('lastExec')->eq($compile->updateDate)
->set('lastStatus')->eq($build->status)
->set('lastExec')->eq($build->updateDate)
->where('id')->eq($job->id)
->exec();
+1 -1
View File
@@ -21,7 +21,7 @@
<label class="radio-inline"><input type="radio" name="product" value="<?php echo $key?>"<?php echo $key == $checkedKey ? " checked='checked'" : ''?> id="product<?php echo $key;?>"><?php echo $value;?></label>
<?php endforeach;?>
</td>
<td><span class='alert alert-info no-margin'><?php echo $lang->custom->notice->readOnlyOfProduct;?></span></td>
<td><div class='alert alert-info no-margin'><?php echo $lang->custom->notice->readOnlyOfProduct;?></div></td>
</tr>
<tr>
<th></th>
+3 -3
View File
@@ -8,11 +8,11 @@ $lang->datatable->reset = 'Reset';
$lang->datatable->custom = 'Customize Columns';
$lang->datatable->customTip = 'Check columns to display and drag columns to order.';
$lang->datatable->switchToTable = 'Switch to Common Table';
$lang->datatable->switchToDatatable = 'Switch to Advanced Table';
$lang->datatable->switchToTable = 'Common Table';
$lang->datatable->switchToDatatable = 'Advanced Table';
$lang->datatable->required = 'Required';
$lang->datatable->confirmReset = 'Do you want to restore the default settings?';
$lang->datatable->setGlobal = 'Set as Global';
$lang->datatable->setGlobal = 'Set Global';
$lang->datatable->resetGlobal = 'Global Reset';
$lang->datatable->branch = 'Branch';
+1 -1
View File
@@ -13,7 +13,7 @@ $lang->dept->common = 'Department';
$lang->dept->id = 'ID';
$lang->dept->path = 'Path';
$lang->dept->position = 'Position';
$lang->dept->manageChild = "Child Department";
$lang->dept->manageChild = "Department";
$lang->dept->edit = "Edit Department";
$lang->dept->delete = "Delete Department";
$lang->dept->parent = "Parent Dept";
+32
View File
@@ -0,0 +1,32 @@
<?php
$config->design = new stdclass();
$config->design->editor = new stdclass();
$config->design->editor->create = array('id' => 'desc', 'tools' => 'simpleTools');
$config->design->editor->edit = array('id' => 'desc', 'tools' => 'simpleTools');
$config->design->editor->assignto = array('id' => 'comment', 'tools' => 'simpleTools');
$config->design->create = new stdclass();
$config->design->edit = new stdclass();
$config->design->create->requiredFields = 'name,type';
$config->design->edit->requiredFields = 'name,type';
$config->design->affectedFixedNum = 7;
global $lang;
$config->design->search['module'] = 'design';
$config->design->search['fields']['id'] = $lang->design->id;
$config->design->search['fields']['type'] = $lang->design->type;
$config->design->search['fields']['name'] = $lang->design->name;
$config->design->search['fields']['commit'] = $lang->design->submission;
$config->design->search['fields']['createdBy'] = $lang->design->createdBy;
$config->design->search['fields']['createdDate'] = $lang->design->createdDate;
$config->design->search['fields']['assignedTo'] = $lang->design->assignedTo;
$config->design->search['fields']['story'] = $lang->design->story;
$config->design->search['params']['type'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->design->typeList);
$config->design->search['params']['name'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
$config->design->search['params']['commit'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
$config->design->search['params']['createdBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->design->search['params']['createdDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->design->search['params']['assignedTo'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->design->search['params']['story'] = array('operator' => '=', 'control' => 'select', 'values' => '');
+485
View File
@@ -0,0 +1,485 @@
<?php
/**
* The control file of design module of ZenTaoPMS.
*
* @copyright Copyright 2009-2020 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: control.php 5107 2020-09-02 09:46:12Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
class design extends control
{
/**
* Construct function, load module auto.
*
* @param string $moduleName
* @param string $methodName
* @access public
* @return void
*/
public function __construct($moduleName = '', $methodName = '')
{
parent::__construct($moduleName, $methodName);
$this->loadModel('product');
$this->loadModel('project');
$this->loadModel('task');
}
/**
* Design common action.
*
* @param int $projectID
* @param int $productID
* @param int $designID
* @access public
* @return void
*/
public function commonAction($projectID = 0, $productID = 0, $designID = 0)
{
$products = $this->product->getProductPairsByProject($projectID);
$productID = $this->product->saveState($productID, $products);
$this->lang->modulePageNav = $this->design->setMenu($projectID, $products, $productID);
$this->project->setMenu($projectID);
$this->view->products = $products;
return $productID;
}
/**
* Browse designs.
*
* @param int $projectID
* @param int $productID
* @param string $type all|bySearch|HLDS|DDS|DBDS|ADS
* @param string $param
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function browse($projectID = 0, $productID = 0, $type = 'all', $param = '', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$productID = $this->commonAction($projectID, $productID);
/* Save session for design list and process product id. */
$this->session->set('designList', $this->app->getURI(true), 'project');
/* Build the search form. */
$queryID = ($type == 'bySearch') ? (int)$param : 0;
$actionURL = $this->createLink('design', 'browse', "projectID=$projectID&productID=$productID&type=bySearch&queryID=myQueryID");
$this->design->buildSearchForm($queryID, $actionURL);
/* Print top and right actions. */
$this->lang->TRActions = '<div class="btn-group dropdown">';
$this->lang->TRActions .= html::a(inlink('create', "projectID=$projectID&productID=$productID&type=$type"), "<i class='icon-plus'></i> {$this->lang->design->create}", '', "class='btn btn-primary'");
$this->lang->TRActions .= "<button type='button' class='btn btn-primary dropdown-toggle' data-toggle='dropdown'><span class='caret'></span>";
$this->lang->TRActions .= '</button>';
$this->lang->TRActions .= "<ul class='dropdown-menu pull-right' id='createActionMenu'>";
if(common::hasPriv('design', 'create')) $this->lang->TRActions .= '<li>' . html::a($this->createLink('design', 'create', "projectID=$projectID&productID=$productID&type=$type"), $this->lang->design->create, '', "class='btn btn-link'") . '</li>';
if(common::hasPriv('design', 'batchCreate')) $this->lang->TRActions .= '<li>' . html::a($this->createLink('design', 'batchCreate', "projectID=$projectID&productID=$productID&type=$type"), $this->lang->design->batchCreate, '', "class='btn btn-link'") . '</li>';
$this->lang->TRActions .= '</ul>';
$this->lang->TRActions .= '</div>';
/* Init pager and get designs. */
$this->app->loadClass('pager', $static = true);
$pager = pager::init(0, $recPerPage, $pageID);
$designs = $this->design->getList($projectID, $productID, $type, $queryID, $orderBy, $pager);
$this->view->title = $this->lang->design->common . $this->lang->colon . $this->lang->design->browse;
$this->view->position[] = $this->lang->design->browse;
$this->view->designs = $designs;
$this->view->type = $type;
$this->view->param = $param;
$this->view->orderBy = $orderBy;
$this->view->productID = $productID;
$this->view->projectID = $projectID;
$this->view->pager = $pager;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->display();
}
/**
* Create a design.
*
* @param int $projectID
* @param int $productID
* @param string $type
* @access public
* @return void
*/
public function create($projectID = 0, $productID = 0, $type = 'all')
{
$productID = $this->commonAction($projectID, $productID);
if($_POST)
{
$designID = $this->design->create($projectID);
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
return $this->send($response);
}
$this->loadModel('action')->create('design', $designID, 'created');
$response['result'] = 'success';
$response['message'] = $this->lang->saveSuccess;
$response['locate'] = $this->createLink('design', 'browse', "projectID=$projectID&productID=$productID");
return $this->send($response);
}
$this->view->title = $this->lang->design->common . $this->lang->colon . $this->lang->design->create;
$this->view->position[] = $this->lang->design->create;
$this->view->users = $this->loadModel('user')->getPairs('noclosed');
$this->view->stories = $this->loadModel('story')->getProductStoryPairs($productID);
$this->view->productID = $productID;
$this->view->type = $type;
$this->view->project = $this->loadModel('project')->getByID($projectID);
$this->display();
}
/**
* Batch create designs.
*
* @param int $projectID
* @param int $productID
* @param string $type
* @access public
* @return void
*/
public function batchCreate($projectID = 0, $productID = 0, $type = 'all')
{
$productID = $this->commonAction($projectID, $productID);
if($_POST)
{
$this->design->batchCreate($projectID, $productID);
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
return $this->send($response);
}
$response['result'] = 'success';
$response['message'] = $this->lang->saveSuccess;
$response['locate'] = inlink('browse', "projectID=$projectID&productID=$productID");
return $this->send($response);
}
$this->view->title = $this->lang->design->common . $this->lang->colon . $this->lang->design->batchCreate;
$this->view->position[] = $this->lang->design->batchCreate;
$this->view->stories = $this->loadModel('story')->getProductStoryPairs($productID);
$this->view->users = $this->loadModel('user')->getPairs('noclosed');
$this->view->type = $type;
$this->display();
}
/**
* View a design.
*
* @param int $designID
* @access public
* @return void
*/
public function view($designID = 0)
{
$design = $this->design->getByID($designID);
$productID = $this->commonAction($design->project, $design->product, $designID);
$this->view->title = $this->lang->design->common . $this->lang->colon . $this->lang->design->view;
$this->view->position[] = $this->lang->design->view;
$this->view->design = $design;
$this->view->stories = $this->loadModel('story')->getProductStoryPairs($design->product);
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->actions = $this->loadModel('action')->getList('design', $design->id);
$this->display();
}
/**
* Edit a design.
*
* @param int $designID
* @access public
* @return void
*/
public function edit($designID = 0)
{
$design = $this->design->getByID($designID);
$design = $this->design->getAffectedScope($design);
$productID = $this->commonAction($design->project, $design->product, $designID);
if($_POST)
{
$changes = $this->design->update($designID);
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
return $this->send($response);
}
if(!empty($changes))
{
$actionID = $this->loadModel('action')->create('design', $designID, 'changed');
$this->action->logHistory($actionID, $changes);
}
$response['result'] = 'success';
$response['message'] = $this->lang->saveSuccess;
$response['locate'] = $this->createLink('design', 'view', "id=$design->id");
return $this->send($response);
}
$this->view->title = $this->lang->design->common . $this->lang->colon . $this->lang->design->edit;
$this->view->position[] = $this->lang->design->edit;
$this->view->design = $design;
$this->view->project = $this->loadModel('project')->getByID($design->project);
$this->view->stories = $this->loadModel('story')->getProductStoryPairs($design->product);
$this->display();
}
/**
* Design link commits.
*
* @param int $designID
* @param int $repoID
* @param string $begin
* @param string $end
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function linkCommit($designID = 0, $repoID = 0, $begin = '', $end = '', $recTotal = 0, $recPerPage = 50, $pageID = 1)
{
$design = $this->design->getById($designID);
$productID = $this->commonAction($design->project, $design->product, $designID);
/* Get project and date. */
$project = $this->loadModel('project')->getByID($design->project);
$begin = $begin ? date('Y-m-d', strtotime($begin)) : $project->begin;
$end = $end ? date('Y-m-d', strtotime($end)) : helper::today();
/* Get the repository information through the repoID. */
$repos = $this->loadModel('repo')->getRepoPairs($design->project);
$repoID = $repoID ? $repoID : key($repos);
if(empty($repoID)) die(js::locate(helper::createLink('repo', 'create', "objectID=$design->project")));
$repo = $this->loadModel('repo')->getRepoByID($repoID);
$revisions = $this->repo->getCommits($repo, '', 'HEAD', '', '', $begin, $end);
if($_POST)
{
$this->design->linkCommit($designID, $repoID);
$result['result'] = 'success';
$result['message'] = $this->lang->saveSuccess;
$result['locate'] = 'parent';
return $this->send($result);
}
/* Linked submission. */
$linkedRevisions = array();
$relations = $this->loadModel('common')->getRelations('design', $designID, 'commit');
foreach($relations as $relation) $linkedRevisions[$relation->BID] = $relation->BID;
foreach($revisions as $id => $commit)
{
if(isset($linkedRevisions[$commit->id])) unset($revisions[$id]);
}
/* Init pager. */
$this->app->loadClass('pager', $static = true);
$recTotal = count($revisions);
$pager = new pager($recTotal, $recPerPage, $pageID);
$revisions = array_chunk($revisions, $pager->recPerPage);
$this->view->title = $this->lang->design->common . $this->lang->colon . $this->lang->design->linkCommit;
$this->view->position[] = $this->lang->design->linkCommit;
$this->view->repos = $repos;
$this->view->repoID = $repoID;
$this->view->repo = $repo;
$this->view->revisions = empty($revisions) ? $revisions : $revisions[$pageID - 1];
$this->view->designID = $designID;
$this->view->begin = $begin;
$this->view->end = $end;
$this->view->design = $this->design->getByID($designID);
$this->view->pager = $pager;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->display();
}
/**
* Design unlink commits.
*
* @param int $designID
* @param int $commitID
* @param string $confirm
* @access public
* @return void
*/
public function unlinkCommit($designID = 0, $commitID = 0, $confirm = 'no')
{
if($confirm == 'no')
{
die(js::confirm($this->lang->design->confirmUnlink, inlink('unlinkCommit', "designID=$designID&commitID=$commitID&confirm=yes")));
}
else
{
$this->design->unlinkCommit($designID, $commitID);
die(js::reload('parent'));
}
}
/**
* View a design's commit.
*
* @param int $designID
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function viewCommit($designID = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$design = $this->design->getByID($designID);
$productID = $this->commonAction($design->project, $design->product, $designID);
/* Init pager. */
$this->app->loadClass('pager', $static = true);
$pager = pager::init(0, $recPerPage, $pageID);
$this->view->title = $this->lang->design->common . $this->lang->colon . $this->lang->design->submission;
$this->view->position[] = $this->lang->design->submission;
$this->view->design = $this->design->getCommit($designID, $pager);
$this->view->pager = $pager;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->display();
}
/**
* A version of the repository.
*
* @param int $repoID
* @param int $projectID
* @access public
* @return void
*/
public function revision($repoID = 0, $projectID = 0)
{
$repo = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('id')->eq($repoID)->fetch();
$repoURL = $this->createLink('repo', 'revision', "repoID=$repo->repo&objectID=$projectID&revistion=$repo->revision");
header("location:" . $repoURL);
}
/**
* Ajax get design drop menu.
*
* @param int $projectID
* @param int $productID
* @param string $extra
* @access public
* @return void
*/
public function ajaxGetDropMenu($projectID, $productID)
{
$products = $this->loadModel('product')->getProducts($projectID);
$this->view->link = helper::createLink('design', 'browse', "projectID=$projectID&productID=%s");
$this->view->productID = $productID;
$this->view->products = $products;
$this->view->projectID = $projectID;
$this->display();
}
/**
* Delete a design.
*
* @param int $designID
* @param string $confirm
* @access public
* @return void
*/
public function delete($designID = 0, $confirm = 'no')
{
if($confirm == 'no')
{
die(js::confirm($this->lang->design->confirmDelete, inlink('delete', "designID=$designID&confirm=yes")));
}
else
{
$this->design->delete(TABLE_DESIGN, $designID);
$this->dao->delete()->from(TABLE_RELATION)->where('Atype')->eq('design')->andWhere('AID')->eq($designID)->andWhere('Btype')->eq('commit')->andwhere('relation')->eq('completedin')->exec();
$this->dao->delete()->from(TABLE_RELATION)->where('Atype')->eq('commit')->andWhere('BID')->eq($designID)->andWhere('Btype')->eq('design')->andwhere('relation')->eq('completedfrom')->exec();
die(js::locate($this->session->designList, 'parent'));
}
}
/**
* Update assign of design.
*
* @param int $designID
* @access public
* @return void
*/
public function assignTo($designID = 0)
{
if($_POST)
{
$changes = $this->design->assign($designID);
if(dao::isError()) die(js::error(dao::getError()));
$this->loadModel('action');
if(!empty($changes))
{
$actionID = $this->action->create('design', $designID, 'Assigned', $this->post->comment, $this->post->assignedTo);
$this->action->logHistory($actionID, $changes);
}
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('design', 'browse'), 'parent'));
}
$design = $this->design->getByID($designID);
$this->view->title = $this->lang->design->common . $this->lang->colon . $this->lang->design->assignedTo;
$this->view->position[] = $this->lang->design->assignedTo;
$this->view->design = $design;
$this->view->users = $this->loadModel('project')->getTeamMemberPairs($design->project);
$this->display();
}
}
+3
View File
@@ -0,0 +1,3 @@
#featurebar {display:inline-block;}
#querybox #searchform {border-bottom: 1px solid #ddd; margin-bottom: 20px;}
#designTable td {white-space:nowrap; text-overflow:ellipsis; overflow: hidden}
+1
View File
@@ -0,0 +1 @@
.tabs .tab-pane .table{border: 1px solid #ddd; border-top: none}
+8
View File
@@ -0,0 +1,8 @@
#mainContent {min-height: 350px;}
.searchBox{min-height: 45px;}
.searchBox .srearch-date{float: left; width: 20%}
.searchBox h4{float:left;display: inline-block}
.searchBox span{float:left;line-height:30px}
#logForm .table thead th{background: #efefef}
#begin{margin-right:5px}
#end{margin-left:5px}
+4
View File
@@ -0,0 +1,4 @@
$(function()
{
$('#subNavbar .nav li[data-id=' + type.toLowerCase() + ']').addClass('active');
})
+5
View File
@@ -0,0 +1,5 @@
$(function()
{
$('#subNavbar .nav li').removeClass('active');
$('#subNavbar .nav li[data-id=' + type + ']').addClass('active');
})
+16
View File
@@ -0,0 +1,16 @@
$(document).on('click', '.ajaxPager', function()
{
$('#logBox').load($(this).attr('href'));
return false;
})
$('#product').change(function()
{
productID = $(this).val();
var link = createLink('story', 'ajaxGetProductStories', 'productID=' + productID);
$.post(link, function(data)
{
$('#story').replaceWith(data);
$('#story_chosen').remove();
$('#story').chosen();
})
})
+4
View File
@@ -0,0 +1,4 @@
$(function()
{
$('#subNavbar .nav li[data-id=' + type.toLowerCase() + ']').addClass('active');
})
+4
View File
@@ -0,0 +1,4 @@
$(function()
{
$('#subNavbar .nav li[data-id=' + type.toLowerCase() + ']').addClass('active');
})
+28
View File
@@ -0,0 +1,28 @@
$('#begin, #end, #repo').change(function()
{
var begin = $('#begin').val();
var end = $('#end').val();
var repo = $('#repo').val();
if(begin.indexOf('-') != -1)
{
var beginarray = begin.split("-");
var begin = '';
for(i = 0; i < beginarray.length; i++) begin = begin + beginarray[i];
}
if(end.indexOf('-') != -1)
{
var endarray = end.split("-");
var end = '';
for(i = 0 ; i < endarray.length ; i++) end = end + endarray[i];
}
if(begin > end)
{
alert(errorDate);
location.href = createLink('design', 'linkCommit', "designID=" + designID + '&repoID=' + repo);
die;
}
location.href = createLink('design', 'linkCommit', "designID=" + designID + '&repoID=' + repo + '&begin=' + begin + '&end=' + end);
})
+4
View File
@@ -0,0 +1,4 @@
$(function()
{
$('#subNavbar .nav li[data-id=' + type.toLowerCase() + ']').addClass('active');
})
+78
View File
@@ -0,0 +1,78 @@
<?php
/**
* The English file of design module.
*
* @copyright Copyright 2009-2020 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: en.php 4729 2020-09-01 07:53:55Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
/* 字段列表. */
$lang->design->id = 'ID';
$lang->design->name = 'Name';
$lang->design->story = 'Story';
$lang->design->type = 'Type';
$lang->design->ditto = 'Ditto';
$lang->design->submission = 'Commit';
$lang->design->version = 'Revision';
$lang->design->assignedTo = 'AssignedTo';
$lang->design->actions = 'Actions';
$lang->design->byQuery = 'Search';
$lang->design->products = 'Linked Product';
$lang->design->story = 'Linked Story';
$lang->design->file = 'File';
$lang->design->desc = 'Description';
$lang->design->range = 'Impact';
$lang->design->product = 'Linked Product';
$lang->design->basicInfo = 'Basic Information';
$lang->design->commitBy = 'Commit By';
$lang->design->commitDate = 'Committed Date';
$lang->design->affectedStory = "{$lang->SRCommon}";
$lang->design->affectedTasks = 'Task';
$lang->design->reviewObject = 'Review Object';
$lang->design->createdBy = 'CreatedBy';
$lang->design->createdDate = 'CreatedDate';
$lang->design->basicInfo = 'Basic Information';
$lang->design->noAssigned = 'Unassigned';
$lang->design->comment = 'Comment';
/* 动作列表. */
$lang->design->common = 'Design';
$lang->design->create = 'Create Design';
$lang->design->batchCreate = 'Batch Create';
$lang->design->edit = 'Edit';
$lang->design->delete = 'Delete';
$lang->design->view = 'View';
$lang->design->browse = 'List';
$lang->design->viewCommit = 'View Commit';
$lang->design->linkCommit = 'Link Commit';
$lang->design->unlinkCommit = 'Unlink Commit';
$lang->design->submit = 'Submit Review';
$lang->design->assignTo = 'Assign';
$lang->design->revision = 'Linked Code';
/* 字段取值. */
$lang->design->typeList = array();
$lang->design->typeList[''] = '';
$lang->design->typeList['HLDS'] = 'High-Level';
$lang->design->typeList['DDS'] = 'Detailed';
$lang->design->typeList['DBDS'] = 'Database';
$lang->design->typeList['ADS'] = 'API';
$lang->design->rangeList = array();
$lang->design->rangeList['all'] = 'All';
$lang->design->rangeList['assign'] = 'Selected';
$lang->design->featureBar['all'] = 'All';
$lang->design->featureBar += $lang->design->typeList;
/* 提示信息. */
$lang->design->errorSelection = 'No record selected!';
$lang->design->noDesign = 'No record.';
$lang->design->noCommit = 'No record commited.';
$lang->design->confirmDelete = 'Do you want to delete this design?';
$lang->design->confirmUnlink = 'Are you sure you want to remove this submission?';
$lang->design->errorDate = 'The start date can not be greater than the end date.';
$lang->design->deleted = 'Deleted';
+80
View File
@@ -0,0 +1,80 @@
<?php
/**
* The English file of design module.
*
* @copyright Copyright 2009-2020 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: en.php 4729 2020-09-01 07:53:55Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
/* 字段列表. */
$lang->design->id = 'ID';
$lang->design->name = 'Name';
$lang->design->story = 'Story';
$lang->design->type = 'Type';
$lang->design->ditto = 'Ditto';
$lang->design->submission = 'Commit';
$lang->design->version = 'Revision';
$lang->design->assignedTo = 'AssignedTo';
$lang->design->actions = 'Actions';
$lang->design->byQuery = 'Search';
$lang->design->products = 'Linked Product';
$lang->design->story = 'Linked Story';
$lang->design->file = 'File';
$lang->design->desc = 'Description';
$lang->design->range = 'Impact';
$lang->design->product = 'Linked Product';
$lang->design->basicInfo = 'Basic Information';
$lang->design->commitBy = 'Commit By';
$lang->design->commitDate = 'Committed Date';
$lang->design->affectedStory = "{$lang->SRCommon}";
$lang->design->affectedTasks = 'Task';
$lang->design->reviewObject = 'Review Object';
$lang->design->createdBy = 'CreatedBy';
$lang->design->createdDate = 'CreatedDate';
$lang->design->basicInfo = 'Basic Information';
$lang->design->noAssigned = 'Unassigned';
$lang->design->comment = 'Comment';
/* 动作列表. */
$lang->design->common = 'Design';
$lang->design->create = 'Create Design';
$lang->design->batchCreate = 'Batch Create';
$lang->design->edit = 'Edit';
$lang->design->delete = 'Delete';
$lang->design->view = 'View';
$lang->design->browse = 'List';
$lang->design->viewCommit = 'View Commit';
$lang->design->linkCommit = 'Link Commit';
$lang->design->unlinkCommit = 'Unlink Commit';
$lang->design->submit = 'Submit Review';
$lang->design->assignTo = 'Assign';
$lang->design->revision = 'Linked Code';
$lang->design->browseAction = 'Design List';
/* 字段取值. */
$lang->design->typeList = array();
$lang->design->typeList[''] = '';
$lang->design->typeList['HLDS'] = 'High-Level';
$lang->design->typeList['DDS'] = 'Detailed';
$lang->design->typeList['DBDS'] = 'Database';
$lang->design->typeList['ADS'] = 'API';
$lang->design->rangeList = array();
$lang->design->rangeList['all'] = 'All';
$lang->design->rangeList['assign'] = 'Selected';
$lang->design->featureBar['all'] = 'All';
$lang->design->featureBar += $lang->design->typeList;
/* 提示信息. */
$lang->design->errorSelection = 'No record selected!';
$lang->design->noDesign = 'No record.';
$lang->design->noCommit = 'No record commited.';
$lang->design->confirmDelete = 'Do you want to delete this design?';
$lang->design->confirmUnlink = 'Are you sure you want to remove this submission?';
$lang->design->errorDate = 'The start date can not be greater than the end date.';
$lang->design->deleted = 'Deleted';
+78
View File
@@ -0,0 +1,78 @@
<?php
/**
* The English file of design module.
*
* @copyright Copyright 2009-2020 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: en.php 4729 2020-09-01 07:53:55Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
/* 字段列表. */
$lang->design->id = 'ID';
$lang->design->name = 'Name';
$lang->design->story = 'Story';
$lang->design->type = 'Type';
$lang->design->ditto = 'Ditto';
$lang->design->submission = 'Commit';
$lang->design->version = 'Revision';
$lang->design->assignedTo = 'AssignedTo';
$lang->design->actions = 'Actions';
$lang->design->byQuery = 'Search';
$lang->design->products = 'Linked Product';
$lang->design->story = 'Linked Story';
$lang->design->file = 'File';
$lang->design->desc = 'Description';
$lang->design->range = 'Impact';
$lang->design->product = 'Linked Product';
$lang->design->basicInfo = 'Basic Information';
$lang->design->commitBy = 'Commit By';
$lang->design->commitDate = 'Committed Date';
$lang->design->affectedStory = "{$lang->SRCommon}";
$lang->design->affectedTasks = 'Task';
$lang->design->reviewObject = 'Review Object';
$lang->design->createdBy = 'CreatedBy';
$lang->design->createdDate = 'CreatedDate';
$lang->design->basicInfo = 'Basic Information';
$lang->design->noAssigned = 'Unassigned';
$lang->design->comment = 'Comment';
/* 动作列表. */
$lang->design->common = 'Design';
$lang->design->create = 'Create Design';
$lang->design->batchCreate = 'Batch Create';
$lang->design->edit = 'Edit';
$lang->design->delete = 'Delete';
$lang->design->view = 'View';
$lang->design->browse = 'List';
$lang->design->viewCommit = 'View Commit';
$lang->design->linkCommit = 'Link Commit';
$lang->design->unlinkCommit = 'Unlink Commit';
$lang->design->submit = 'Submit Review';
$lang->design->assignTo = 'Assign';
$lang->design->revision = 'Linked Code';
/* 字段取值. */
$lang->design->typeList = array();
$lang->design->typeList[''] = '';
$lang->design->typeList['HLDS'] = 'High-Level';
$lang->design->typeList['DDS'] = 'Detailed';
$lang->design->typeList['DBDS'] = 'Database';
$lang->design->typeList['ADS'] = 'API';
$lang->design->rangeList = array();
$lang->design->rangeList['all'] = 'All';
$lang->design->rangeList['assign'] = 'Selected';
$lang->design->featureBar['all'] = 'All';
$lang->design->featureBar += $lang->design->typeList;
/* 提示信息. */
$lang->design->errorSelection = 'No record selected!';
$lang->design->noDesign = 'No record.';
$lang->design->noCommit = 'No record commited.';
$lang->design->confirmDelete = 'Do you want to delete this design?';
$lang->design->confirmUnlink = 'Are you sure you want to remove this submission?';
$lang->design->errorDate = 'The start date can not be greater than the end date.';
$lang->design->deleted = 'Deleted';
+78
View File
@@ -0,0 +1,78 @@
<?php
/**
* The English file of design module.
*
* @copyright Copyright 2009-2020 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: en.php 4729 2020-09-01 07:53:55Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
/* 字段列表. */
$lang->design->id = 'ID';
$lang->design->name = 'Name';
$lang->design->story = 'Story';
$lang->design->type = 'Type';
$lang->design->ditto = 'Ditto';
$lang->design->submission = 'Commit';
$lang->design->version = 'Revision';
$lang->design->assignedTo = 'AssignedTo';
$lang->design->actions = 'Actions';
$lang->design->byQuery = 'Search';
$lang->design->products = 'Linked Product';
$lang->design->story = 'Linked Story';
$lang->design->file = 'File';
$lang->design->desc = 'Description';
$lang->design->range = 'Impact';
$lang->design->product = 'Linked Product';
$lang->design->basicInfo = 'Basic Information';
$lang->design->commitBy = 'Commit By';
$lang->design->commitDate = 'Committed Date';
$lang->design->affectedStory = "{$lang->SRCommon}";
$lang->design->affectedTasks = 'Task';
$lang->design->reviewObject = 'Review Object';
$lang->design->createdBy = 'CreatedBy';
$lang->design->createdDate = 'CreatedDate';
$lang->design->basicInfo = 'Basic Information';
$lang->design->noAssigned = 'Unassigned';
$lang->design->comment = 'Comment';
/* 动作列表. */
$lang->design->common = 'Design';
$lang->design->create = 'Create Design';
$lang->design->batchCreate = 'Batch Create';
$lang->design->edit = 'Edit';
$lang->design->delete = 'Delete';
$lang->design->view = 'View';
$lang->design->browse = 'List';
$lang->design->viewCommit = 'View Commit';
$lang->design->linkCommit = 'Link Commit';
$lang->design->unlinkCommit = 'Unlink Commit';
$lang->design->submit = 'Submit Review';
$lang->design->assignTo = 'Assign';
$lang->design->revision = 'Linked Code';
/* 字段取值. */
$lang->design->typeList = array();
$lang->design->typeList[''] = '';
$lang->design->typeList['HLDS'] = 'High-Level';
$lang->design->typeList['DDS'] = 'Detailed';
$lang->design->typeList['DBDS'] = 'Database';
$lang->design->typeList['ADS'] = 'API';
$lang->design->rangeList = array();
$lang->design->rangeList['all'] = 'All';
$lang->design->rangeList['assign'] = 'Selected';
$lang->design->featureBar['all'] = 'All';
$lang->design->featureBar += $lang->design->typeList;
/* 提示信息. */
$lang->design->errorSelection = 'No record selected!';
$lang->design->noDesign = 'No record.';
$lang->design->noCommit = 'No record commited.';
$lang->design->confirmDelete = 'Do you want to delete this design?';
$lang->design->confirmUnlink = 'Are you sure you want to remove this submission?';
$lang->design->errorDate = 'The start date can not be greater than the end date.';
$lang->design->deleted = 'Deleted';
+80
View File
@@ -0,0 +1,80 @@
<?php
/**
* The zh-cn file of design module.
*
* @copyright Copyright 2009-2020 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: zh-cn.php 4729 2020-09-01 07:53:55Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
/* 字段列表. */
$lang->design->id = '编号';
$lang->design->name = '设计名称';
$lang->design->story = '需求';
$lang->design->type = '设计类型';
$lang->design->ditto = '同上';
$lang->design->submission = '相关提交';
$lang->design->version = '版本号';
$lang->design->assignedTo = '指派给';
$lang->design->actions = '操作';
$lang->design->byQuery = '搜索';
$lang->design->products = '所属产品';
$lang->design->story = '相关需求';
$lang->design->file = '附件';
$lang->design->desc = '设计描述';
$lang->design->range = '影响范围';
$lang->design->product = '所属产品';
$lang->design->basicInfo = '基础信息';
$lang->design->commitBy = '由谁提交';
$lang->design->commitDate = '提交时间';
$lang->design->affectedStory = "影响{$lang->SRCommon}";
$lang->design->affectedTasks = '影响任务';
$lang->design->reviewObject = '评审对象';
$lang->design->createdBy = '由谁创建';
$lang->design->createdDate = '创建时间';
$lang->design->basicInfo = '基本信息';
$lang->design->noAssigned = '未指派';
$lang->design->comment = '注释';
/* 动作列表. */
$lang->design->common = '设计';
$lang->design->create = '创建设计';
$lang->design->batchCreate = '批量创建';
$lang->design->edit = '变更';
$lang->design->delete = '删除';
$lang->design->view = '设计概况';
$lang->design->browse = '浏览列表';
$lang->design->viewCommit = '查看提交';
$lang->design->linkCommit = '关联提交';
$lang->design->unlinkCommit = '取消关联';
$lang->design->submit = '提交评审';
$lang->design->assignTo = '指派';
$lang->design->revision = '查看关联代码';
$lang->design->browseAction = '设计列表';
/* 字段取值. */
$lang->design->typeList = array();
$lang->design->typeList[''] = '';
$lang->design->typeList['HLDS'] = '概要设计';
$lang->design->typeList['DDS'] = '详细设计';
$lang->design->typeList['DBDS'] = '数据库设计';
$lang->design->typeList['ADS'] = '接口设计';
$lang->design->rangeList = array();
$lang->design->rangeList['all'] = '全部记录';
$lang->design->rangeList['assign'] = '选中记录';
$lang->design->featureBar['all'] = '所有';
$lang->design->featureBar += $lang->design->typeList;
/* 提示信息. */
$lang->design->errorSelection = '还没有选中记录!';
$lang->design->noDesign = '暂时没有记录';
$lang->design->noCommit = '暂时没有提交记录';
$lang->design->confirmDelete = '您确定要删除这个设计吗?';
$lang->design->confirmUnlink = '您确定要移除这个提交吗?';
$lang->design->errorDate = '开始日期不能大于结束日期';
$lang->design->deleted = '已删除';
+78
View File
@@ -0,0 +1,78 @@
<?php
/**
* The zh-tw file of design module.
*
* @copyright Copyright 2009-2020 青島易軟天創網絡科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: zh-tw.php 4729 2020-09-01 07:53:55Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
/* 欄位列表. */
$lang->design->id = '編號';
$lang->design->name = '設計名稱';
$lang->design->story = '需求';
$lang->design->type = '設計類型';
$lang->design->ditto = '同上';
$lang->design->submission = '相關提交';
$lang->design->version = '版本號';
$lang->design->assignedTo = '指派給';
$lang->design->actions = '操作';
$lang->design->byQuery = '搜索';
$lang->design->products = '所屬產品';
$lang->design->story = '相關需求';
$lang->design->file = '附件';
$lang->design->desc = '設計描述';
$lang->design->range = '影響範圍';
$lang->design->product = '所屬產品';
$lang->design->basicInfo = '基礎信息';
$lang->design->commitBy = '由誰提交';
$lang->design->commitDate = '提交時間';
$lang->design->affectedStory = "影響{$lang->SRCommon}";
$lang->design->affectedTasks = '影響任務';
$lang->design->reviewObject = '評審對象';
$lang->design->createdBy = '由誰創建';
$lang->design->createdDate = '創建時間';
$lang->design->basicInfo = '基本信息';
$lang->design->noAssigned = '未指派';
$lang->design->comment = '註釋';
/* 動作列表. */
$lang->design->common = '設計';
$lang->design->create = '創建設計';
$lang->design->batchCreate = '批量創建';
$lang->design->edit = '變更';
$lang->design->delete = '刪除';
$lang->design->view = '設計概況';
$lang->design->browse = '瀏覽列表';
$lang->design->viewCommit = '查看提交';
$lang->design->linkCommit = '關聯提交';
$lang->design->unlinkCommit = '取消關聯';
$lang->design->submit = '提交評審';
$lang->design->assignTo = '指派';
$lang->design->revision = '查看關聯代碼';
/* 欄位取值. */
$lang->design->typeList = array();
$lang->design->typeList[''] = '';
$lang->design->typeList['HLDS'] = '概要設計';
$lang->design->typeList['DDS'] = '詳細設計';
$lang->design->typeList['DBDS'] = '資料庫設計';
$lang->design->typeList['ADS'] = '介面設計';
$lang->design->rangeList = array();
$lang->design->rangeList['all'] = '全部記錄';
$lang->design->rangeList['assign'] = '選中記錄';
$lang->design->featureBar['all'] = '所有';
$lang->design->featureBar += $lang->design->typeList;
/* 提示信息. */
$lang->design->errorSelection = '還沒有選中記錄!';
$lang->design->noDesign = '暫時沒有記錄';
$lang->design->noCommit = '暫時沒有提交記錄';
$lang->design->confirmDelete = '您確定要刪除這個設計嗎?';
$lang->design->confirmUnlink = '您確定要移除這個提交嗎?';
$lang->design->errorDate = '開始日期不能大於結束日期';
$lang->design->deleted = '已刪除';
+465
View File
@@ -0,0 +1,465 @@
<?php
/**
* The model file of design module of ZenTaoPMS.
*
* @copyright Copyright 2009-2020 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: model.php 5107 2020-09-02 09:46:12Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
?>
<?php
class designModel extends model
{
/**
* Create a design.
*
* @param int $projectID
* @access public
* @return void
*/
public function create($projectID)
{
$design = fixer::input('post')
->stripTags('desc', $this->config->allowedTags)
->add('createdBy', $this->app->user->account)
->add('createdDate', helper::now())
->add('project', $projectID)
->add('version', 1)
->remove('files,labels')
->get();
$design = $this->loadModel('file')->processImgURL($design, 'desc', $this->post->uid);
$this->dao->insert(TABLE_DESIGN)->data($design)
->autoCheck()
->batchCheck($this->config->design->create->requiredFields, 'notempty')
->exec();
if(!dao::isError())
{
$designID = $this->dao->lastInsertID();
$this->file->updateObjectID($this->post->uid, $designID, 'design');
$files = $this->file->saveUpload('design', $designID);
$spec = new stdclass();
$spec->design = $designID;
$spec->version = 1;
$spec->name = $design->name;
$spec->desc = $design->desc;
$spec->files = empty($files) ? '' : implode(',', array_keys($files));
$this->dao->insert(TABLE_DESIGNSPEC)->data($spec)->exec();
return $designID;
}
return false;
}
/**
* Batch create designs.
*
* @param int $projectID
* @param int $productID
* @access public
* @return bool
*/
public function batchCreate($projectID = 0, $productID = 0)
{
$data = fixer::input('post')->get();
$this->loadModel('action');
foreach($data->name as $i => $name)
{
if(!trim($name)) continue;
$design = new stdclass();
$design->story = isset($data->story[$i]) ? $data->story[$i] : '';
$design->type = $data->type[$i];
$design->name = $name;
$design->product = $productID;
$design->project = $projectID;
$design->createdBy = $this->app->user->account;
$design->createdDate = helper::now();
$this->dao->insert(TABLE_DESIGN)->data($design)->autoCheck()->batchCheck($this->config->design->create->requiredFields, 'notempty')->exec();
$designID = $this->dao->lastInsertID();
$this->action->create('design', $designID, 'Opened');
}
return true;
}
/**
* Update a design.
*
* @param int $designID
* @access public
* @return bool
*/
public function update($designID = 0)
{
$oldDesign = $this->getByID($designID);
$design = fixer::input('post')
->add('editedBy', $this->app->user->account)
->add('editedDate', helper::now())
->stripTags($this->config->design->editor->edit['id'], $this->config->allowedTags)
->remove('file,files,labels,children,toList')
->get();
$design = $this->loadModel('file')->processImgURL($design, 'desc', $this->post->uid);
$this->dao->update(TABLE_DESIGN)->data($design)->autoCheck()->batchCheck('name,type', 'notempty')->where('id')->eq($designID)->exec();
if(!dao::isError())
{
$this->file->updateObjectID($this->post->uid, $designID, 'design');
$files = $this->file->saveUpload('design', $designID);
$designChanged = ($oldDesign->name != $design->name || $oldDesign->desc != $design->desc || !empty($files));
if($designChanged)
{
$design = $this->getByID($designID);
$version = $design->version + 1;
$spec = new stdclass();
$spec->design = $designID;
$spec->version = $version;
$spec->name = $design->name;
$spec->desc = $design->desc;
$spec->files = empty($files) ? '' : implode(',', array_keys($files));
$this->dao->insert(TABLE_DESIGNSPEC)->data($spec)->exec();
$this->dao->update(TABLE_DESIGN)->set('version')->eq($version)->where('id')->eq($designID)->exec();
}
return common::createChanges($oldDesign, $design);
}
return false;
}
/**
* Assign a design.
*
* @param int $designID
* @access public
* @return array|bool
*/
public function assign($designID = 0)
{
$oldDesign = $this->getByID($designID);
$design = fixer::input('post')
->add('editedBy', $this->app->user->account)
->add('editedDate', helper::today())
->setDefault('assignedDate', helper::today())
->stripTags($this->config->design->editor->assignto['id'], $this->config->allowedTags)
->remove('uid,comment,files,label')
->get();
$this->dao->update(TABLE_DESIGN)->data($design)->autoCheck()->where('id')->eq((int)$designID)->exec();
if(!dao::isError()) return common::createChanges($oldDesign, $design);
return false;
}
/**
* LinkCommit a design.
*
* @param int $designID
* @param int $repoID
* @access public
* @return void
*/
public function linkCommit($designID = 0, $repoID = 0)
{
$revisions = $_POST['revision'];
foreach($revisions as $revision)
{
$data = new stdclass();
$data->project = $this->session->project;
$data->product = $this->session->product;
$data->AType = 'design';
$data->AID = $designID;
$data->BType = 'commit';
$data->BID = $revision;
$data->relation = 'completedin';
$data->extra = $repoID;
$this->dao->replace(TABLE_RELATION)->data($data)->autoCheck()->exec();
$data->AType = 'commit';
$data->AID = $revision;
$data->BType = 'design';
$data->BID = $designID;
$data->relation = 'completedfrom';
$this->dao->replace(TABLE_RELATION)->data($data)->autoCheck()->exec();
}
$oldCommit = $this->dao->findByID($designID)->from(TABLE_DESIGN)->fetch('commit');
$revisions = join(',', $revisions);
$commit = $oldCommit ? $oldCommit . ',' . $revisions : $revisions;
$design = new stdclass();
$design->commit = $commit;
$design->commitedBy = $this->app->user->account;
$this->dao->update(TABLE_DESIGN)->data($design)->autoCheck()->where('id')->eq($designID)->exec();
}
/**
* Unlink commit.
*
* @param int $designID
* @param int $commitID
* @access public
* @return void
*/
public function unlinkCommit($designID = 0, $commitID = 0)
{
/* Delete data in the zt_relation.*/
$this->dao->delete()->from(TABLE_RELATION)->where('AType')->eq('design')->andwhere('AID')->eq($designID)->andwhere('BType')->eq('commit')->andwhere('relation')->eq('completedin')->andWhere('BID')->eq($commitID)->exec();
$this->dao->delete()->from(TABLE_RELATION)->where('AType')->eq('commit')->andwhere('BID')->eq($designID)->andwhere('BType')->eq('design')->andwhere('relation')->eq('completedfrom')->andWhere('AID')->eq($commitID)->exec();
/* Commit after unlinking. */
$commit = $this->dao->select('BID')->from(TABLE_RELATION)->where('AType')->eq('design')->andWhere('AID')->eq($designID)->andWhere('BType')->eq('commit')->andwhere('relation')->eq('completedin')->fetchAll('BID');
$commit = implode(",", array_keys($commit));
$this->dao->update(TABLE_DESIGN)->set('commit')->eq($commit)->where('id')->eq($designID)->exec();
}
/**
* Get a design by id.
*
* @param int $designID
* @access public
* @return object
*/
public function getByID($designID = 0)
{
$design = $this->dao->select('*')->from(TABLE_DESIGN)->where('id')->eq($designID)->fetch();
if(!$design) return false;
$design->files = $this->loadModel('file')->getByObject('design', $designID);
$design->productName = $this->dao->findByID($design->product)->from(TABLE_PRODUCT)->fetch('name');
$design->commit = '';
$relations = $this->loadModel('common')->getRelations('design', $designID, 'commit');
foreach($relations as $relation) $design->commit .= html::a(helper::createLink('design', 'revision', "repoID=$relation->BID&projectID={$design->project}"), "#$relation->BID", '_blank');
return $this->loadModel('file')->replaceImgURL($design, 'desc');
}
/**
* Get design pairs.
*
* @param int $productID
* @param string $type all|HLDS|DDS|DBDS|ADS
* @access public
* @return object
*/
public function getPairs($productID = 0, $type = 'all')
{
$designs = $this->dao->select('id, name')->from(TABLE_DESIGN)
->where('product')->eq($productID)
->andWhere('deleted')->eq(0)
->andWhere('type')->eq($type)
->fetchPairs();
foreach($designs as $id => $name) $designs[$id] = $id . ':' . $name;
return $designs;
}
/**
* Get affected scope.
*
* @param int $design
* @access public
* @return object
*/
public function getAffectedScope($design = 0)
{
/* Get affected tasks. */
$design->tasks = $this->dao->select('*')->from(TABLE_TASK)
->where('deleted')->eq(0)
->andWhere('status')->ne('closed')
->andWhere('design')->eq($design->id)
->orderBy('id desc')->fetchAll();
return $design;
}
/**
* Get design list.
*
* @param int $productID
* @param int $projectID
* @param string $type all|bySearch|HLDS|DDS|DBDS|ADS
* @param int $param
* @param string $orderBy
* @param int $pager
* @access public
* @return array
*/
public function getList($projectID = 0, $productID = 0, $type = 'all', $param = 0, $orderBy = 'id_desc', $pager = null)
{
if($type == 'bySearch')
{
$designs = $this->getBySearch($projectID, $productID, $param, $orderBy, $pager);
}
else
{
$designs = $this->dao->select('*')->from(TABLE_DESIGN)
->where('deleted')->eq(0)
->beginIF($projectID)->andWhere('project')->eq($projectID)->fi()
->beginIF($type != 'all')->andWhere('type')->in($type)->fi()
->andWhere('product')->eq($productID)
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
}
return $designs;
}
/**
* Get commit.
*
* @param int $designID
* @param int $pager
* @access public
* @return object
*/
public function getCommit($designID = 0, $pager = null)
{
$design = $this->dao->select('*')->from(TABLE_DESIGN)->where('id')->eq($designID)->fetch();
$design->commit = $this->dao->select('*')->from(TABLE_REPOHISTORY)->where('id')->in($design->commit)->page($pager)->fetchAll('id');
return $design;
}
/**
* Get designs by search.
*
* @param int $projectID
* @param int $productID
* @param int $queryID
* @param string $orderBy
* @param int $pager
* @access public
* @return object
*/
public function getBySearch($projectID = 0, $productID = 0, $queryID = 0, $orderBy = 'id_desc', $pager = null)
{
if($queryID)
{
$query = $this->loadModel('search')->getQuery($queryID);
if($query)
{
$this->session->set('designQuery', $query->sql);
$this->session->set('designForm', $query->form);
}
else
{
$this->session->set('designQuery', ' 1 = 1');
}
}
else
{
if($this->session->designQuery == false) $this->session->set('designQuery', ' 1 = 1');
}
$designQuery = $this->session->designQuery;
$designs = $this->dao->select('*')->from(TABLE_DESIGN)
->where($designQuery)
->andWhere('deleted')->eq('0')
->andWhere('project')->eq($projectID)
->andWhere('product')->eq($productID)
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
return $designs;
}
/**
* Set design menu.
*
* @param int $projectID
* @param int $products
* @param int $productID
* @param string $currentModule
* @param string $currentMethod
* @param string $extra
* @param int $branch
* @access public
* @return void
*/
public function setMenu($projectID = 0, $products, $productID = 0)
{
if($this->app->rawMethod != 'browse') unset($this->lang->waterfall->menu->design['subMenu']->bysearch);
if(empty($products) || !$productID) return '';
$currentProduct = $this->loadModel('product')->getById($productID);
setCookie("lastProduct", $productID, $this->config->cookieLife, $this->config->webRoot, '', false, true);
$output = '';
if(!empty($products))
{
$dropMenuLink = helper::createLink('design', 'ajaxGetDropMenu', "projectID=$projectID&productID=$productID");
$output = "<div class='btn-group angle-btn'><div class='btn-group'><button data-toggle='dropdown' type='button' class='btn btn-limit' id='currentItem' title='{$currentProduct->name}'><span class='text'>{$currentProduct->name}</span> <span class='caret'></span></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";
$output .= '<div class="input-control search-box has-icon-left has-icon-right search-example"><input type="search" class="form-control search-input" /><label class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label><a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a></div>';
$output .= "</div></div></div>";
}
return $output;
}
/**
* Build search form.
*
* @param int $queryID
* @param string $actionURL
* @access public
* @return void
*/
public function buildSearchForm($queryID = 0, $actionURL = '')
{
$this->config->design->search['actionURL'] = $actionURL;
$this->config->design->search['queryID'] = $queryID;
$this->loadModel('search')->setSearchParams($this->config->design->search);
}
/**
* Print assignedTo html.
*
* @param object $design
* @param array $users
* @access public
* @return string
*/
public function printAssignedHtml($design = '', $users = '')
{
$btnTextClass = '';
$assignedToText = zget($users, $design->assignedTo);
if(empty($design->assignedTo))
{
$btnTextClass = 'text-primary';
$assignedToText = $this->lang->design->noAssigned;
}
if($design->assignedTo == $this->app->user->account) $btnTextClass = 'text-red';
$btnClass = $design->assignedTo == 'closed' ? ' disabled' : '';
$btnClass = "iframe btn btn-icon-left btn-sm {$btnClass}";
$assignToLink = helper::createLink('design', 'assignTo', "designID=$design->id", '', true);
$assignToHtml = html::a($assignToLink, "<i class='icon icon-hand-right'></i> <span title='" . zget($users, $design->assignedTo) . "' class='{$btnTextClass}'>{$assignedToText}</span>", '', "class='$btnClass'");
echo !common::hasPriv('design', 'assignTo', $design) ? "<span style='padding-left: 21px' class='{$btnTextClass}'>{$assignedToText}</span>" : $assignToHtml;
}
}
@@ -0,0 +1,64 @@
<?php js::set('productID', $productID);?>
<?php
$iCharges = 0;
$others = 0;
$closeds = 0;
$tab = 'project';
$productNames = array();
foreach($products as $product)
{
if($product->status == 'normal' and $product->PO == $this->app->user->account) $iCharges++;
if($product->status == 'normal' and !($product->PO == $this->app->user->account)) $others++;
if($product->status == 'closed') $closeds++;
$productNames[] = $product->name;
}
$productsPinYin = common::convert2Pinyin($productNames);
$myProductsHtml = '';
$normalProductsHtml = '';
$closedProductsHtml = '';
foreach($products as $product)
{
$selected = $product->id == $productID ? 'selected' : '';
$productName = $product->name;
$linkHtml = sprintf($link, $product->id);
if($product->status == 'normal' and $product->PO == $this->app->user->account)
{
$myProductsHtml .= html::a($linkHtml, $productName, '', "class='text-important $selected' title='{$productName}' data-key='" . zget($productsPinYin, $product->name, '') . "' data-app='$tab'");
}
else if($product->status == 'normal' and !($product->PO == $this->app->user->account))
{
$normalProductsHtml .= html::a($linkHtml, $productName, '', "class='$selected' title='{$productName}' data-key='" . zget($productsPinYin, $product->name, '') . "' data-app='$tab'");
}
else if($product->status == 'closed')
{
$closedProductsHtml .= html::a($linkHtml, $productName, '', "class='$selected' title='{$productName}' class='closed' data-key='" . zget($productsPinYin, $product->name, '') . "' data-app='$tab'");
}
}
?>
<div class="table-row">
<div class="table-col col-left">
<div class='list-group'>
<?php
if(!empty($myProductsHtml))
{
echo "<div class='heading'>{$lang->product->mine}</div>";
echo $myProductsHtml;
if(!empty($myProductsHtml))
{
echo "<div class='heading'>{$lang->product->other}</div>";
}
}
echo $normalProductsHtml;
?>
</div>
<div class="col-footer">
<a class='pull-right toggle-right-col not-list-item'><?php echo $lang->product->closed?><i class='icon icon-angle-right'></i></a>
</div>
</div>
<div class="table-col col-right">
<div class='list-group'><?php echo $closedProductsHtml;?></div>
</div>
</div>
<script>scrollToSelected();</script>
+40
View File
@@ -0,0 +1,40 @@
<?php
/**
* The assignTo of design module of ZenTaoPMS.
*
* @copyright Copyright 2009-2020 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: assignto.html.php 4903 2020-09-02 09:32:59Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
?>
<?php include "../../common/view/header.html.php";?>
<?php include '../../common/view/kindeditor.html.php';?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2>
<span class='prefix label-id'><strong><?php echo $design->id;?></strong></span>
<?php echo "<span title='$design->name'>" . $design->name . '</span>';?>
</h2>
</div>
<form class='load-indicator main-form' method='post' target='hiddenwin'>
<table class='table table-form'>
<tbody>
<tr>
<th class='w-100px'><?php echo $lang->design->assignedTo;?></th>
<td><?php echo html::select('assignedTo', $users, $design->assignedTo, "class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->comment;?></th>
<td colspan='2'><?php echo html::textarea('comment', '', "rows='6' class='form-control kindeditor' hidefocus='true'");?></td>
</tr>
<tr>
<td class='text-center form-actions' colspan='3'><?php echo html::submitButton(); ?></td> </tr>
</tbody>
</table>
</form>
</div>
<?php include "../../common/view/footer.html.php";?>
+45
View File
@@ -0,0 +1,45 @@
<?php
/**
* The batchCreate view of design module of ZenTaoPMS.
*
* @copyright Copyright 2009-2020 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: batchcreate.html.php 4903 2020-09-02 09:32:59Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php js::set('type', $type);?>
<div id="mainContent" class="main-content fade">
<div class="main-header"><h2><?php echo $lang->design->batchCreate;?></h2></div>
<form class="load-indicator main-form form-ajax" method='post' enctype='multipart/form-data' id='dataform'>
<table class="table table-form">
<thead>
<tr>
<th class='w-50px'><?php echo $lang->design->id;?></th>
<th class='w-200px'><?php echo $lang->design->story;?></th>
<th class='w-200px required'><?php echo $lang->design->type;?></th>
<th class='required'><?php echo $lang->design->name;?></th>
</tr>
</thead>
<tbody>
<?php for($i = 1; $i <= 10; $i ++):?>
<tr>
<td><?php echo $i;?></td>
<td><?php echo html::select("story[$i]", $stories, '', "class='form-control chosen'");?></td>
<td><?php echo html::select("type[$i]", $lang->design->typeList, '', "class='form-control chosen'");?></td>
<td><?php echo html::input("name[$i]", '', "class='form-control'");?></td>
</tr>
<?php endfor;?>
<tr>
<td colspan='4' class='form-actions text-center'>
<?php echo html::submitButton() . html::backButton();?>
</td>
</tr>
</tbody>
</table>
</form>
</div>
<?php include '../../common/view/footer.html.php';?>
+69
View File
@@ -0,0 +1,69 @@
<?php
/**
* The browse view file of design module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: browse.html.php 5102 2020-09-03 10:59:54Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/sortable.html.php';?>
<?php js::set('type', strtolower($type));?>
<style>
.btn-group a i.icon-plus {font-size: 16px;}
.btn-group a.btn-primary {border-right: 1px solid rgba(255,255,255,0.3);}
.btn-group button.dropdown-toggle.btn-primary {padding:6px;}
</style>
<div class="cell<?php if($type == 'bySearch') echo ' show';?>" id="queryBox" data-module='design'></div>
<div id="mainContent" class="main-table">
<?php if(empty($designs)):?>
<div class="table-empty-tip">
<p><span class="text-muted"><?php echo $lang->design->noDesign;?></span></p>
</div>
<?php else:?>
<form id='designFrom' method='post' class="main-table">
<table class='table has-sort-head table-fixrd' id="designTable">
<?php $vars = "projectID=$projectID&productID=$productID&type=$type&param=$param&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}";?>
<thead>
<tr>
<th class="text-left w-60px"> <?php common::printOrderLink('id', $orderBy, $vars, $lang->design->id);?></th>
<th class="text-left w-100px"> <?php common::printOrderLink('type', $orderBy, $vars, $lang->design->type);?></th>
<th class="text-left"> <?php common::printOrderLink('name', $orderBy, $vars, $lang->design->name);?></th>
<th class="text-left w-120px"> <?php common::printOrderLink('createdBy', $orderBy, $vars, $lang->design->createdBy);?></th>
<th class="text-left w-150px"> <?php common::printOrderLink('createdDate', $orderBy, $vars, $lang->design->createdDate);?></th>
<th class="c-assignedTo w-120px"><?php common::printOrderLink('assignedTo', $orderBy, $vars, $lang->design->assignedTo);?></th>
<th class="text-center w-100px"> <?php echo $lang->design->actions;?></th>
</tr>
</thead>
<tbody>
<?php foreach($designs as $design):?>
<tr>
<td calss="c-id"> <?php printf('%03d', $design->id);?></td>
<td class="c-type"> <?php echo zget($lang->design->typeList, $design->type);?></td>
<td class="c-name" title="<?php echo $design->name;?>"><?php echo html::a($this->createLink('design', 'view', "id={$design->id}"), $design->name);?></td>
<td class="c-createdBy"> <?php echo zget($users, $design->createdBy);?></td>
<td class="c-createdDate"><?php echo substr($design->createdDate, 0, 11);?></td>
<td class="c-assignedTo"> <?php echo $this->design->printAssignedHtml($design, $users);?></td>
<td class='c-actions text-center'>
<?php
$vars = "design={$design->id}";
common::printIcon('design', 'edit', $vars, $design, 'list', 'alter', '', '', '', '', '', $design->project);
common::printIcon('design', 'viewCommit', $vars, $design, 'list', 'list-alt', '', 'iframe showinonlybody', true);
common::printIcon('design', 'delete', $vars, $design, 'list', 'trash', 'hiddenwin', '', '', '', '', $design->project);
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='table-footer table-statistic'>
<?php $pager->show('right', 'pagerjs');?>
</div>
</form>
<?php endif;?>
</div>
<?php include '../../common/view/footer.html.php';?>
+60
View File
@@ -0,0 +1,60 @@
<?php
/**
* The create view of design module of ZenTaoPMS.
*
* @copyright Copyright 2009-2020 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: create.html.php 4903 2020-09-02 09:32:59Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('type', $type);?>
<div id="mainContent" class="main-content fade">
<div class="center-block">
<div class="main-header">
<h2><?php echo $lang->design->create;?></h2>
</div>
<form class="load-indicator main-form form-ajax" method='post' enctype='multipart/form-data' id='dataform'>
<table class="table table-form">
<tbody>
<tr>
<th class='w-120px'><?php echo $lang->design->product;?></th>
<td><?php echo html::select('product', $products, $productID, "class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
<th class='w-120px'><?php echo $lang->design->story;?></th>
<td><?php echo html::select('story', empty($stories) ? '' : $stories, '', "class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->design->type;?></th>
<td><?php echo html::select('type', $lang->design->typeList, '', "class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->design->name;?></th>
<td><?php echo html::input('name', '', "class='form-control'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->design->desc;?></th>
<td colspan='2'><?php echo html::textarea('desc', '', "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->design->file;?></th>
<td colspan='2'><?php echo $this->fetch('file', 'buildform', 'fileCount=1&percent=0.85');?></td>
</tr>
<tr>
<td colspan='3' class='text-center form-actions'><?php echo html::submitButton() . html::backButton();?></td>
</tr>
</tbody>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+98
View File
@@ -0,0 +1,98 @@
<?php
/**
* The edit view of design module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: edit.html.php 4903 2020-09-02 09:32:59Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('type', $design->type);?>
<div id="mainContent" class="main-content fade">
<div class="center-block">
<div class="main-header">
<h2><?php echo $lang->design->edit;?></h2>
</div>
<form class="load-indicator main-form form-ajax" method='post' enctype='multipart/form-data' id='dataform'>
<table class="table table-form">
<tbody>
<tr>
<th class='w-120px'><?php echo $lang->design->product;?></th>
<td><?php echo html::select('product', $products, $design->product, "class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
<th class='w-120px'><?php echo $lang->design->story;?></th>
<td><?php echo html::select('story', empty($stories) ? '' : $stories, $design->story, "class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->design->type;?></th>
<td><?php echo html::select('type', $lang->design->typeList, $design->type, "class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->design->name;?></th>
<td><?php echo html::input('name', $design->name, "class='form-control'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->design->desc;?></th>
<td colspan='2'><?php echo html::textarea('desc', $design->desc, 'class="form-control"');?></td>
</tr>
<tr>
<th><?php echo $lang->design->file;?></th>
<td colspan='2'><?php echo $this->fetch('file', 'buildform', 'fileCount=1&percent=0.85');?></td>
</tr>
<tr>
<th><?php echo $lang->story->checkAffection;?></th>
<td colspan='2'>
<div class='tabs'>
<ul class='nav nav-tabs'>
<li class='active'><a data-toggle='tab' href='#affectedTasks'><?php echo $lang->design->affectedTasks;?><span class='label label-danger label-badge label-circle'><?php echo count($design->tasks);?></span></a></li>
</ul>
<div class='tab-content'>
<div class='tab-pane active' id='affectedTasks'>
<table class='table'>
<thead>
<tr class='text-center'>
<th class='c-id'> <?php echo $lang->task->id;?></th>
<th class='c-name'> <?php echo $lang->task->name;?></th>
<th class='w-100px'> <?php echo $lang->task->assignedTo;?></th>
<th class='c-status'><?php echo $lang->task->status;?></th>
<th class='w-100px'> <?php echo $lang->task->consumed;?></th>
<th class='w-90px'> <?php echo $lang->task->left;?></th>
</tr>
</thead>
<tbody>
<?php foreach($design->tasks as $task):?>
<tr class='text-center'>
<td><?php $task->id?></td>
<td class='text-left'><?php echo html::a($this->createLink('task', 'view', "taskID=$task->id"), $task->name, '_blank');?></td>;
<td><?php echo zget($users, $task->assignedTo);?></td>
<td><span class='status-task status-<?php echo $task->status;?>'><?php $this->processStatus('task', $task);?></span></td>
<td><?php echo $task->consumed;?></td>
<td><?php echo $task->left;?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</div>
</div>
</div>
</td>
</tr>
<tr>
<td colspan='3' class='text-center form-actions'><?php echo html::submitButton() . html::backButton();?></td>
</tr>
</tbody>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+88
View File
@@ -0,0 +1,88 @@
<?php
/**
* The linkCommit view of design module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: linkcommit.html.php 4903 2020-09-02 09:32:59Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div class='main-content' id='mainContent'>
<div class='main-header'>
<h2>
<span class='label label-id'><?php echo $design->id;?></span>
<span title='<?php echo $design->name?>'><?php echo $design->name?></span>
<small><?php echo $lang->arrow . $lang->design->linkCommit;?></small>
</h2>
</div>
<?php if(empty($repoID)):?>
<div class="table-empty-tip">
<p><span class="text-muted"><?php echo $lang->design->noCommit;?></span></p>
</div>
<?php else:?>
<div class='searchBox'>
<table class="table">
<tr>
<td class="w-100px"><h4><?php echo $lang->repo->maintain . ': ';?></h4></td>
<td><?php echo html::select('repo', $repos, $repoID, "class='form-control chosen'");?></td>
<td>
<h4><?php echo $lang->design->commitDate . ':';?></h4>
<?php echo html::input('begin', $begin, "class='form-control form-date srearch-date'");?>
<span>~</span>
<?php echo html::input('end', $end, "class='form-control form-date srearch-date'");?>
</td>
</tr>
</table>
</div>
<form id='logForm' class='main-table form-ajax' data-ride='table' action=<?php echo inlink('linkCommit', "designID=$designID&repoID=$repoID");?> method='post'>
<table class='table'>
<thead>
<tr>
<th class='w-40px'></th>
<th class='w-100px'><?php echo $lang->repo->revisionA?></th>
<?php if(isset($repo->SCM) and $repo->SCM == 'Git'):?>
<th class='w-70px'><?php echo $lang->repo->commit?></th>
<?php endif;?>
<th class='w-120px'><?php echo $lang->repo->time?></th>
<th class='w-100px'><?php echo $lang->repo->committer?></th>
<th><?php echo $lang->repo->comment?></th>
</tr>
</thead>
<tbody>
<?php foreach($revisions as $log):?>
<tr>
<td class='c-name'>
<div class='checkbox-primary'>
<input type='checkbox' name='revision[]' value="<?php echo $log->id?>"/>
<label></label>
</div>
</td>
<td class='versions c-name' title="<?php echo $repo->SCM == 'Git' ? substr($log->revision, 0, 10) : $log->revision;?>"><span class="revision"><?php echo html::a($this->repo->createLink('revision', "repoID=$repoID&revision={$log->revision}"), $repo->SCM == 'Git' ? substr($log->revision, 0, 10) : $log->revision);?></span></td>
<?php if($repo->SCM == 'Git'):?>
<td><?php echo $log->commit?></td>
<?php endif;?>
<td><?php echo substr($log->time, 0, 10);?></td>
<td><?php echo zget($users, $log->committer, $log->committer);?></td>
<?php $comment = htmlspecialchars($log->comment, ENT_QUOTES);?>
<td title='<?php echo $comment?>' class='comment c-name'><?php echo $log->comment?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='table-footer'>
<div class="checkbox-primary check-all"><label><?php echo $lang->selectAll?></label></div>
<div class="table-actions btn-toolbar">
<?php echo html::submitButton('', '', 'btn btn-primary')?>
</div>
<?php $pager->show('right', 'pagerjs');?>
</div>
</form>
<?php endif;?>
</div>
<?php js::set('designID', $designID);?>
<?php js::set('errorDate', $lang->design->errorDate);?>
<?php include '../../common/view/footer.html.php';?>
+92
View File
@@ -0,0 +1,92 @@
<?php
/**
* The view of design module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: view.html.php 4903 2020-09-02 09:32:59Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php js::set('type', $design->type);?>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
<?php $browseLink = $app->session->designList != false ? $app->session->designList : $this->createLink('design', 'browse', "productID=$design->product");?>
<?php if(!isonlybody()) echo html::a($browseLink, '<i class="icon icon-back icon-sm"></i> ' . $lang->goback, '', "class='btn btn-secondary'");?>
<div class="divider"></div>
<div class="page-title">
<span class="label label-id"><?php echo $design->id?></span>
<span class="text" title="<?php echo $design->name;?>"><?php echo $design->name;?></span>
<?php if($design->deleted):?>
<span class='label label-danger'><?php echo $lang->design->deleted;?></span>
<?php endif; ?>
</div>
</div>
</div>
<div id="mainContent" class="main-row">
<div class="main-col col-8">
<div class="cell">
<div class="detail">
<div class="detail-title"><?php echo $lang->design->desc;?></div>
<div class="detail-content article-content">
<?php echo $design->desc;?>
</div>
</div>
<?php echo $this->fetch('file', 'printFiles', array('files' => $design->files, 'fieldset' => 'true'));?>
</div>
<div class='cell'><?php include '../../common/view/action.html.php';?></div>
<div class='main-actions'>
<div class="btn-toolbar">
<?php common::printBack($this->session->designList);?>
<?php if(!isonlybody()) echo "<div class='divider'></div>";?>
<?php if(!$design->deleted):?>
<?php
common::printIcon('design', 'assignTo', "designID=$design->id", $design, 'button', '', '', 'iframe showinonlybody', true);
common::printIcon('design', 'linkCommit', "designID=$design->id", $design, 'button', 'link', '', 'iframe showinonlybody', true);
common::printIcon('design', 'edit', "designID=$design->id", $design, 'button', 'alter');
common::printIcon('design', 'delete', "designID=$design->id", $design, 'button', 'trash', 'hiddenwin');
?>
<?php endif;?>
</div>
</div>
</div>
<div class='side-col col-4'>
<div class='cell'>
<div class="detail">
<div class='detail-title'><?php echo $lang->design->basicInfo;?></div>
<div class='detail-content'>
<table class='table table-data'>
<tr>
<th><?php echo $lang->design->type;?></th>
<td><?php echo zget($lang->design->typeList, $design->type);?></td>
</tr>
<tr>
<th><?php echo $lang->design->product;?></th>
<td><?php echo $design->productName;?></td>
</tr>
<tr>
<th><?php echo $lang->design->story;?></th>
<td><?php echo $design->story ? html::a($this->createLink('story', 'view', "id=$design->story"), zget($stories, $design->story)) : '';?></td>
</tr>
<tr>
<th><?php echo $lang->design->submission;?></th>
<td><?php echo $design->commit;?></td>
</tr>
<tr>
<th><?php echo $lang->design->createdBy;?></th>
<td><?php echo zget($users, $design->createdBy);?></td>
</tr>
<tr>
<th><?php echo $lang->design->createdDate;?></th>
<td><?php echo substr($design->createdDate, 0, 11);?></td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+63
View File
@@ -0,0 +1,63 @@
<?php
/**
* The viewCommit view of design module of ZenTaoPMS.
*
* @copyright Copyright 2009-2020 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian <tianshujie@easycorp.ltd>
* @package design
* @version $Id: viewcommit.html.php 4903 2020-09-02 09:32:59Z tianshujie@easycorp.ltd $
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<style>
#mainContent .pull-right{margin-bottom: 10px}
.table{border: 1px solid #ddd;}
</style>
<div id="mainContent">
<div class='main-header'>
<h2>
<span class='label label-id'><?php echo $design->id;?></span>
<span title='<?php echo $design->name?>'><?php echo $design->name?></span>
<small><?php echo $lang->arrow . $lang->design->submission;?></small>
</h2>
</div>
<div class='btn-toolbar pull-right'>
<?php common::printLink('design', 'linkCommit', "designID=$design->id", "<i class='icon icon-plus'></i>" . $lang->design->linkCommit, '_blank', "class='btn btn-primary'");?>
</div>
<?php if(empty($design->commit)):?>
<div class="table-empty-tip">
<p><span class="text-muted"><?php echo $lang->design->noCommit;?></span></p>
</div>
<?php else:?>
<table class='table'>
<thead>
<tr>
<th class="w-100px"><?php echo $lang->design->submission;?></th>
<th class='w-120px'><?php echo $lang->design->commitBy;?></th>
<th class='w-100px'><?php echo $lang->design->commitDate;?></th>
<th><?php echo $lang->design->comment;?></th>
<th class="text-center w-50px"> <?php echo $lang->design->actions;?></th>
</tr>
</thead>
<tbody>
<?php foreach($design->commit as $commit):?>
<tr>
<td title="<?php echo $commit->id;?>"><?php echo html::a(helper::createLink('design', 'revision', "repoID=$commit->id"), "#$commit->id", '_blank');?></td>
<td><?php echo zget($users, $commit->committer, $commit->committer);?></td>
<td><?php echo substr($commit->time, 0, 11);?></td>
<td title="<?php echo $commit->comment;?>"><?php echo $commit->comment;?></td>
<td class="c-actions text-center">
<?php common::printIcon('design', 'unlinkCommit', "designID=$design->id&commitID=$commit->id", $design, 'list', 'unlink', 'hiddenwin', 'iframe showinonlybody', true);?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='table-footer table-statistic'>
<?php $pager->show('right', 'pagerjs');?>
</div>
<?php endif;?>
</div>
<?php include '../../common/view/footer.html.php';?>
+3
View File
@@ -96,3 +96,6 @@ ol, ul {margin-bottom: 0}
.c-product, .c-execution, .c-lib {width: 80px !important;}
.header-btn .btn > .text {text-overflow: unset !important;}
.tree li.active > .tree-group a {font-weight: 700; color: #0c64eb;}
.tree li>.list-toggle {left: -4px; top: 0;}
+7 -1
View File
@@ -2,7 +2,7 @@
.addbtn {padding-top: 22px; height: 63px; border: 1px dashed #ddd; width: 60px;}
.addbtn .icon-plus {font-size: 18px; display: block; opacity: 0.5; transition: opacity .2s; text-shadow: 1px 1px 3px rgba(0,0,0,.2);}
.addbtn:hover .icon-plus {opacity: .9; animation: flash-icon 1s linear alternate infinite;}
#subHeader #dropMenu {min-width: 250px; box-sizing: inhert; max-height: inherit;}
#subHeader #dropMenu {min-width: 250px; box-sizing: inherit; max-height: inherit;}
#subHeader #dropMenu .table-col .list-group {padding-top: 10px;}
.main-col .block-files .panel-heading {padding-right: 20px;}
.main-col .block-files .panel-heading .panel-title {height: 35px; line-height: 30px;}
@@ -41,3 +41,9 @@
.title {font-size: 20px !important;}
.article-content.comment {width: 100% !important;}
.tree-group {position: relative;}
.tree-group > .module-name {white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 100%; display: block;}
.tree-group .tree-actions {display: none; position: absolute; right: 0; top: 0; background-color: #fff; white-space: nowrap;}
.tree-group:hover > .module-name {width: calc(100% - 20px);}
.tree-group:hover .tree-actions {display: block}
+1 -1
View File
@@ -133,7 +133,7 @@ $(function()
$('#content').on('click', '.outline .outline-toggle i.icon-angle-right', function()
{
$('.article-content').css('width', '85%');
$('.article-content').width('85%');
$('.outline').css({'min-width' : '180px', 'border-left' : '2px solid #efefef'});
$(this).removeClass('icon-angle-right').addClass('icon-angle-left').css('left', '-9px');
$('.outline-content').show();
+8 -8
View File
@@ -29,12 +29,12 @@ $lang->doc->files = 'Files';
$lang->doc->addedBy = 'Author';
$lang->doc->addedDate = 'Added';
$lang->doc->editedBy = 'UpdatedBy';
$lang->doc->editedDate = 'UpdatedDate';
$lang->doc->editedDate = 'Updated';
$lang->doc->version = 'Version';
$lang->doc->basicInfo = 'Basic Info';
$lang->doc->basicInfo = 'Basic Information';
$lang->doc->deleted = 'Deleted';
$lang->doc->fileObject = 'Dependent Item';
$lang->doc->whiteList = 'White List';
$lang->doc->whiteList = 'Whitelist';
$lang->doc->contentType = 'Format';
$lang->doc->separator = "<i class='icon-angle-right'></i>";
$lang->doc->fileTitle = 'File Name';
@@ -51,7 +51,7 @@ $lang->doc->item = ' Items';
$lang->doc->num = 'Documents';
$lang->doc->searchResult = 'Search Result';
$lang->doc->mailto = 'Mailto';
$lang->doc->noModule = 'No document in this lib, please create it';
$lang->doc->noModule = 'No document in this library. Create one.';
$lang->doc->noChapter = 'No chapters or articles in this book. Please add chapters and articles.';
$lang->doc->views = 'Views';
$lang->doc->draft = 'Draft';
@@ -73,7 +73,7 @@ $lang->doc->todayEdited = 'Updated Today';
$lang->doc->pastEdited = 'Total Updated';
$lang->doc->myDoc = 'My Documents';
$lang->doc->myCollection = 'My Favorites';
$lang->doc->tableContents = 'Catalog';
$lang->doc->tableContents = 'Directory';
/* Methods list */
$lang->doc->index = 'Document Home';
@@ -91,12 +91,12 @@ $lang->doc->manageType = 'Manage Category';
$lang->doc->editType = 'Edit';
$lang->doc->deleteType = 'Delete';
$lang->doc->addType = 'Add';
$lang->doc->childType = 'Catalog';
$lang->doc->catalogName = 'Catalog Name';
$lang->doc->childType = 'Directory';
$lang->doc->catalogName = 'Name';
$lang->doc->collect = 'Add Favorite';
$lang->doc->cancelCollection = 'Remove Favorite';
$lang->doc->deleteFile = 'Delete File';
$lang->doc->menuTitle = 'Menu';
$lang->doc->menuTitle = 'Direcotory';
$lang->doc->collectAction = 'Add Favorite';
+51 -9
View File
@@ -737,7 +737,7 @@ class docModel extends model
}
unset($doc->contentType);
$doc->draft = $doc->content;
$doc->draft = isset($doc->content) ? $doc->content : '';
$this->dao->update(TABLE_DOC)->data($doc, 'content')
->autoCheck()
->batchCheck($requiredFields, 'notempty')
@@ -2274,7 +2274,7 @@ EOT;
if($startModule) $startModulePath = $startModule->path . '%';
}
$docs = $this->dao->select('*')->from(TABLE_DOC)
$docs = $this->dao->select('*')->from(TABLE_DOC)
->where('lib')->eq($rootID)
->andWhere('deleted')->eq(0)
->fetchAll();
@@ -2308,14 +2308,26 @@ EOT;
{
if(!$docID and $currentMethod != 'tablecontents') $docID = $doc->id;
$treeMenu[0] .= '<li' . ($doc->id == $docID ? ' class="active"' : ' class="independent"') . '>';
$treeMenu[0] .= '<li' . ($doc->id == $docID ? ' class="active"' : ' class="independent"') . " data-id=$doc->id>";
if($currentMethod == 'tablecontents')
{
$treeMenu[0] .= '<span class="tail-info">' . zget($users, $doc->editedBy) . ' &nbsp;' . $doc->editedDate . '</span>';
}
$treeMenu[0] .= html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$rootID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title' title='{$doc->title}'");
if($currentMethod == 'objectlibs')
{
$treeMenu[0] .= "<div class='tree-group'><span class='module-name'>" . html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$rootID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title' title='{$doc->title}'") . '</span>';
if(common::hasPriv('doc', 'edit'))
{
$treeMenu[0] .= "<div class='tree-actions'>";
$treeMenu[0] .= html::a(helper::createLink('doc', 'edit', "docID={$doc->id}&comment=false&objectType=$type&objectID=$objectID&libID=$rootID"), "<i class='icon icon-edit'></i>", '', "title={$this->lang->doc->edit}");
$treeMenu[0] .= '</div></div>';
}
}
else
{
$treeMenu[0] .= html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$rootID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title' title='{$doc->title}'");
}
$treeMenu[0] .= '</li>';
}
@@ -2362,13 +2374,28 @@ EOT;
else
{
if(!$docID and $currentMethod != 'tablecontents') $docID = $doc->id;
$treeMenu[$module->id] .= '<li' . ($doc->id == $docID ? ' class="active"' : ' class="doc"') . '>';
$treeMenu[$module->id] .= '<li' . ($doc->id == $docID ? ' class="active"' : ' class="doc"') . " data-id=$doc->id>";
if($currentMethod == 'tablecontents')
{
$treeMenu[$module->id] .= '<span class="tail-info">' . zget($users, $doc->editedBy) . ' &nbsp;' . $doc->editedDate . '</span>';
}
$treeMenu[$module->id] .= html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$libID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title' title='{$doc->title}'");
if($currentMethod == 'objectlibs')
{
$treeMenu[$module->id] .= "<div class='tree-group'><span class='module-name'>" . html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$libID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title' title='{$doc->title}'") . '</span>';
if(common::hasPriv('doc', 'edit'))
{
$treeMenu[$module->id] .= "<div class='tree-actions'>";
$treeMenu[$module->id] .= html::a(helper::createLink('doc', 'edit', "docID=$docID&comment=false&objectType=$type&objectID=$objectID&libID=$libID"), "<i class='icon icon-edit'></i>", '', "title={$this->lang->doc->edit}");
$treeMenu[$module->id] .= '</div>';
}
$treeMenu[$module->id] .= '</div>';
}
elseif($currentMethod == 'tablecontents')
{
$treeMenu[$module->id] .= html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$libID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title' title='{$doc->title}'");
}
$treeMenu[$module->id] .= '</li>';
}
@@ -2381,7 +2408,22 @@ EOT;
}
else
{
$li = "<a title='{$module->name}'>" . $module->name . '</a>';
if($currentMethod == 'tablecontents')
{
$li = "<a title='{$module->name}'>" . $module->name . '</a>';
}
else
{
$li = "<div class='tree-group'><span class='module-name'><a class='sort-module' title='{$module->name}'>" . $module->name . '</a></span>';
if(common::hasPriv('tree', 'edit') or common::hasPriv('tree', 'browse'))
{
$li .= "<div class='tree-actions'>";
if(common::hasPriv('tree', 'edit')) $li .= html::a(helper::createLink('tree', 'edit', "module=$module->id&type=doc"), "<i class='icon icon-edit'></i>", '', "data-toggle='modal' title={$this->lang->doc->editType}");
if(common::hasPriv('tree', 'browse')) $li .= html::a(helper::createLink('tree', 'browse', "rootID=$libID&type=doc&module=$module->id", '', 1), "<i class='icon icon-split'></i>", '', "class='iframe' title={$this->lang->doc->editType}");
$li .= '</div>';
}
$li .= '</div>';
}
}
if($treeMenu[$module->id])
{
@@ -2410,7 +2452,7 @@ EOT;
}
}
$treeMenu[$module->parent] .= '<li class="' . implode(' ', $class) . '">' . $li . '</li>';
$treeMenu[$module->parent] .= '<li class=" can-sort ' . implode(' ', $class) . '" data-id=' . $module->id . '>' . $li . '</li>';
}
/**
+100 -140
View File
@@ -15,149 +15,109 @@ if(empty($type)) $type = 'product';
$sideWidth = common::checkNotCN() ? '270' : '238';
?>
<div class="side-col" style="width:<?php echo $sideWidth;?>px" data-min-width="<?php echo $sideWidth;?>">
<div class="cell" id="<?php echo $type;?>">
<div id='title'>
<li class='menu-title'><?php echo $this->lang->doc->menuTitle;?></li>
<?php
$canEditLib = common::hasPriv('doc', 'editLib');
$canManageBook = common::hasPriv('doc', 'manageBook');
$canManageMenu = common::hasPriv('tree', 'browse');
$canEditLib = common::hasPriv('doc', 'editLib');
$canDeleteLib = common::hasPriv('doc', 'deleteLib');
if($type != 'book' and ($canManageMenu or $canEditLib or $canDeleteLib))
{
echo "<div class='menu-actions'>";
echo html::a('javascript:;', "<i class='icon icon-ellipsis-v'></i>", '', "data-toggle='dropdown' class='btn btn-link'");
echo "<ul class='dropdown-menu pull-right'>";
if($canManageMenu)
{
echo '<li>' . html::a($this->createLink('tree', 'browse', "rootID=$libID&view=doc", '', true), '<i class="icon-cog-outline"></i> ' . $this->lang->doc->manageType, '', "class='iframe'") . '</li>';
echo "<li class='divider'></li>";
}
if($canEditLib) echo '<li>' . html::a($this->createLink('doc', 'editLib', "rootID=$libID"), '<i class="icon-edit"></i> ' . $lang->doc->editLib, '', "class='iframe'") . '</li>';
if($canDeleteLib) echo '<li>' . html::a($this->createLink('doc', 'deleteLib', "rootID=$libID"), '<i class="icon-trash"></i> ' . $lang->doc->deleteLib, 'hiddenwin') . '</li>';
echo '</ul></div>';
}
<div class="cell" id="<?php echo $type;?>">
<div id='title'>
<li class='menu-title'><?php echo $this->lang->doc->menuTitle;?></li>
<?php
$canEditLib = common::hasPriv('doc', 'editLib');
$canManageBook = common::hasPriv('doc', 'manageBook');
$canManageMenu = common::hasPriv('tree', 'browse');
$canEditLib = common::hasPriv('doc', 'editLib');
$canDeleteLib = common::hasPriv('doc', 'deleteLib');
if($type != 'book' and ($canManageMenu or $canEditLib or $canDeleteLib))
{
echo "<div class='menu-actions'>";
echo html::a('javascript:;', "<i class='icon icon-ellipsis-v'></i>", '', "data-toggle='dropdown' class='btn btn-link'");
echo "<ul class='dropdown-menu pull-right'>";
if($canManageMenu)
{
echo '<li>' . html::a($this->createLink('tree', 'browse', "rootID=$libID&view=doc", '', true), '<i class="icon-cog-outline"></i> ' . $this->lang->doc->manageType, '', "class='iframe'") . '</li>';
echo "<li class='divider'></li>";
}
if($canEditLib) echo '<li>' . html::a($this->createLink('doc', 'editLib', "rootID=$libID"), '<i class="icon-edit"></i> ' . $lang->doc->editLib, '', "class='iframe'") . '</li>';
if($canDeleteLib) echo '<li>' . html::a($this->createLink('doc', 'deleteLib', "rootID=$libID"), '<i class="icon-trash"></i> ' . $lang->doc->deleteLib, 'hiddenwin') . '</li>';
echo '</ul></div>';
}
if($type == 'book' and ($canEditLib or $canManageBook))
{
echo "<div class='menu-actions'>";
echo html::a('javascript:;', "<i class='icon icon-ellipsis-v'></i>", '', "data-toggle='dropdown' class='btn btn-link'");
echo "<ul class='dropdown-menu pull-right'>";
if($canEditLib) echo '<li>' . html::a($this->createLink('doc', 'editLib', "rootID=$libID"), '<i class="icon-edit"></i> ' . $lang->doc->editBook, '', "class='iframe'") . '</li>';
if($canManageBook) echo '<li>' . html::a($this->createLink('doc', 'manageBook', "bookID=$libID"), '<i class="icon-cog-outline"></i> ' . $lang->doc->manageBook) . '</li>';
echo '</ul></div>';
}
?>
</div>
<?php if(!$moduleTree):?>
<hr class="space">
<div class="text-center text-muted tips">
<?php echo $type == 'book' ? $lang->doc->noChapter : $lang->doc->noModule;?>
</div>
<hr class="space">
<?php endif;?>
<?php if($type == 'book'):?>
<?php include './bookside.html.php';?>
<?php else:?>
<?php echo $moduleTree;?>
<?php endif;?>
if($type == 'book' and ($canEditLib or $canManageBook))
{
echo "<div class='menu-actions'>";
echo html::a('javascript:;', "<i class='icon icon-ellipsis-v'></i>", '', "data-toggle='dropdown' class='btn btn-link'");
echo "<ul class='dropdown-menu pull-right'>";
if($canEditLib) echo '<li>' . html::a($this->createLink('doc', 'editLib', "rootID=$libID"), '<i class="icon-edit"></i> ' . $lang->doc->editBook, '', "class='iframe'") . '</li>';
if($canManageBook) echo '<li>' . html::a($this->createLink('doc', 'manageBook', "bookID=$libID"), '<i class="icon-cog-outline"></i> ' . $lang->doc->manageBook) . '</li>';
echo '</ul></div>';
}
?>
</div>
<script>
$(function()
{
if($.cookie('docSideType'))
{
var type = $.cookie('docSideType');
var $tabs = $('#mainRow .side-col .tabs');
if($tabs.find('.tab-content .tab-pane#' + type).length >0)
{
$tabs.find('.nav-tabs li').removeClass('active');
$tabs.find('.nav-tabs li a[href="#' + type + '"]').parent().addClass('active');
$tabs.find('.tab-content .tab-pane').removeClass('active');
$tabs.find('.tab-content .tab-pane#' + type).addClass('active');
}
$.cookie('docSideType', '');
$('#mainRow .side-col .side-footer #orderLib').toggleClass('hidden', (type == 'product' || type == 'execution'));
}
<?php if(!$moduleTree):?>
<hr class="space">
<div class="text-center text-muted tips">
<?php echo $type == 'book' ? $lang->doc->noChapter : $lang->doc->noModule;?>
</div>
<hr class="space">
<?php endif;?>
<?php if($type == 'book'):?>
<?php include './bookside.html.php';?>
<?php else:?>
<?php echo $moduleTree;?>
<?php endif;?>
</div>
<style>
.sortable-sorting .module-name > a {cursor: move;}
.sortable-sorting li >.tree-group {opacity: .5;}
.sortable-sorting .drop-here .tree-group {background-color: #fff3e0;}
.sortable-sorting .drop-here .tree-group > * {opacity: .1;}
.sortable-sorting .drag-shadow .tree-group {opacity: 1!important;}
.sortable-sorting .drag-shadow .tree-actions {visibility: hidden;}
.is-sorting > li > .tree-group {opacity: 1; border-radius: 4px;}
.is-sorting > li ul {display: none!important;}
</style>
<script>
$(function()
{
/* Make modules tree sortable */
$('#modules').sortable(
{
trigger: '.module-name>a.sort-module',
dropToClass: 'sort-to',
stopPropagation: true,
nested: true,
selector: 'li',
dragCssClass: 'drop-here',
targetSelector: function($ele, $root)
{
var $ul = $ele.closest('ul');
setTimeout(function()
{
if($('#modules').hasClass('sortable-sorting')) $ul.addClass('is-sorting');
}, 100);
return $ul.children('li');
},
always: function()
{
$('#modules,#modules .is-sorting').removeClass('is-sorting');
},
finish: function(e)
{
if(!e.changed) return;
$('#mainRow .side-col .tabs .nav-tabs li a').click(function()
{
var href = $(this).attr('href');
var canOrder = !(href.indexOf('product') > 0 || href.indexOf('execution') > 0);
if(!canOrder)
{
$(this).closest('.side-col').find('.side-footer #orderLib').addClass('hidden');
$(this).closest('.side-col').find('.side-footer #saveOrder').addClass('hidden');
}
var orders = {};
$('#modules').find('li.can-sort').each(function()
{
var $li = $(this);
var $orderLib = $(this).closest('.side-col').find('.side-footer #orderLib');
var $saveOrder = $(this).closest('.side-col').find('.side-footer #saveOrder');
var item = $li.data();
'<?php echo $type;?>' == 'book' ? orders['sort[' + item.id + ']'] = $li.attr('data-order') || item.order : orders['orders[' + item.id + ']'] = $li.attr('data-order') || item.order;
});
var execute = false;
$(this).on('shown.zui.tab', function()
{
if(!execute)
{
var $tabPane = $('#mainRow .side-col .tabs .tab-content .tab-pane.active');
if($tabPane.find('.libs-group.sort').length > 0 && canOrder)
{
$orderLib.addClass('hidden');
$saveOrder.removeClass('hidden');
execute = true;
}
if($tabPane.find('.libs-group.sort').length == 0 && canOrder)
{
$orderLib.removeClass('hidden');
$saveOrder.addClass('hidden');
execute = true;
}
}
});
});
$('#orderLib').click(function()
{
var $tabPane = $('#mainRow .side-col .tabs .tab-content .tab-pane.active');
var type = $tabPane.attr('id');
$.get(createLink('doc', 'sort', "type=" + type), function(data)
{
$tabPane.html(data);
$tabPane.closest('.side-col').find('.side-footer #orderBox #orderLib').addClass('hidden');
$tabPane.closest('.side-col').find('.side-footer #orderBox #saveOrder').removeClass('hidden');
$tabPane.find('.libs-group.sort').sortable(
{
trigger: '.lib',
selector: '.lib',
});
});
});
});
function saveOrder()
{
var $tabPane = $('#mainRow .side-col .tabs .tab-content .tab-pane.active');
var type = $tabPane.attr('id');
var orders = {};
var orderNext = 1;
$tabPane.find('.libs-group.sort .lib').not('.files').not('.addbtn').each(function()
{
orders[$(this).data('id')] = orderNext ++;
});
$.post(createLink('doc', 'sort'), orders, function(data)
{
if(data.result == 'success')
{
$.cookie('docSideType', type);
return location.reload();
}
else
{
bootbox.alert(data.message);
}
}, 'json');
}
</script>
var link = '<?php echo $type;?>' == 'book' ? createLink('doc', 'sortBookOrder') : createLink('tree', 'updateOrder');
$.post(link, orders, function(data){}).error(function()
{
bootbox.alert(lang.timeout);
});
}
});
});
</script>
</div>
+155 -32
View File
@@ -40,6 +40,7 @@ class execution extends control
$this->loadModel('project');
if(defined('IN_UPGRADE') and IN_UPGRADE) return false;
$this->executions = $this->execution->getPairs(0, 'all', 'nocode');
$skipCreateStep = array('computeburn', 'ajaxgetdropmenu', 'executionkanban', 'ajaxgetteammembers');
if(!in_array($this->methodName, $skipCreateStep) and $this->app->tab == 'execution')
@@ -1266,6 +1267,8 @@ class execution extends control
unset($this->lang->doc->menu->execution['subMenu']);
}
$project = $this->project->getByID($projectID);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
@@ -1516,7 +1519,8 @@ class execution extends control
$executions = array('' => '') + $this->executions;
$execution = $this->execution->getById($executionID);
$managers = $this->execution->getDefaultManagers($executionID);
$managers = $this->execution->getDefaultManagers($executionID);
/* Remove current execution from the executions. */
unset($executions[$executionID]);
@@ -1926,50 +1930,81 @@ class execution extends control
* Kanban.
*
* @param int $executionID
* @param string $type
* @param string $browseType story|bug|task|all
* @param string $orderBy
* @param string $groupBy
* @access public
* @return void
*/
public function kanban($executionID, $type = 'story', $orderBy = 'order_asc')
public function kanban($executionID, $browseType = '', $orderBy = 'order_asc', $groupBy = '')
{
if(empty($browseType)) $browseType = $this->session->kanbanType ? $this->session->kanbanType : 'all';
if(empty($groupBy) and $browseType != 'all') $groupBy = $this->session->{'kanbanGroupBy' . $browseType} ? $this->session->{'kanbanGroupBy' . $browseType} : 'default';
if(empty($groupBy) and $browseType == 'all') $groupBy = 'default';
/* Save to session. */
$uri = $this->app->getURI(true);
$this->app->session->set('taskList', $uri, 'execution');
$this->app->session->set('bugList', $uri, 'qa');
$this->app->session->set('taskList', $uri, 'execution');
$this->app->session->set('bugList', $uri, 'qa');
$this->app->session->set('kanbanType', $browseType, 'execution');
$this->app->session->set('kanbanGroupBy' . $browseType, $groupBy, 'execution');
/* Compatibility IE8*/
/* Load language. */
$this->app->loadLang('story');
$this->app->loadLang('task');
$this->app->loadLang('bug');
/* Compatibility IE8. */
if(strpos($this->server->http_user_agent, 'MSIE 8.0') !== false) header("X-UA-Compatible: IE=EmulateIE7");
$kanbanGroup = $this->loadModel('kanban')->getExecutionKanban($executionID, $browseType, $groupBy);
if(empty($kanbanGroup))
{
$this->kanban->createLanes($executionID, $browseType, $groupBy);
$kanbanGroup = $this->kanban->getExecutionKanban($executionID, $browseType, $groupBy);
}
$this->execution->setMenu($executionID);
$execution = $this->loadModel('execution')->getById($executionID);
$tasks = $this->execution->getKanbanTasks($executionID, "id");
$bugs = $this->loadModel('bug')->getExecutionBugs($executionID);
$stories = $this->loadModel('story')->getExecutionStories($executionID, 0, 0, $orderBy);
/* Determines whether an object is editable. */
$canBeChanged = common::canModify('execution', $execution);
$kanbanGroup = $this->execution->getKanbanGroupData($stories, $tasks, $bugs, $type);
$kanbanSetting = $this->execution->getKanbanSetting();
/* Get execution's product. */
$productID = 0;
$products = $this->loadModel('product')->getProducts($executionID);
if($products) $productID = key($products);
$plans = $this->execution->getPlans($products);
$allPlans = array('' => '');
if(!empty($plans))
{
foreach($plans as $plan) $allPlans += $plan;
}
$userList = array();
$avatarPairs = $this->dao->select('account, avatar')->from(TABLE_USER)->where('deleted')->eq(0)->fetchPairs();
foreach($avatarPairs as $account => $avatar)
{
if(!$avatar) continue;
$userList[$account]['avatar'] = $avatar;
}
$this->view->title = $this->lang->execution->kanban;
$this->view->position[] = html::a($this->createLink('execution', 'browse', "executionID=$executionID"), $execution->name);
$this->view->position[] = $this->lang->execution->kanban;
$this->view->stories = $stories;
$this->view->realnames = $this->loadModel('user')->getPairs('noletter');
$this->view->storyOrder = $orderBy;
$this->view->orderBy = 'id_asc';
$this->view->executionID = $executionID;
$this->view->browseType = '';
$this->view->execution = $execution;
$this->view->type = $type;
$this->view->productID = $productID;
$this->view->allPlans = $allPlans;
$this->view->browseType = $browseType;
$this->view->kanbanGroup = $kanbanGroup;
$this->view->kanbanColumns = $this->execution->getKanbanColumns($kanbanSetting);
$this->view->statusMap = $canBeChanged ? $this->execution->getKanbanStatusMap($kanbanSetting) : array();
$this->view->statusList = $this->execution->getKanbanStatusList($kanbanSetting);
$this->view->colorList = $this->execution->getKanbanColorList($kanbanSetting);
$this->view->execution = $execution;
$this->view->groupBy = $groupBy;
$this->view->canBeChanged = $canBeChanged;
$this->view->userList = $userList;
$this->display();
}
@@ -1984,7 +2019,7 @@ class execution extends control
{
$this->loadModel('project');
$projects = $this->project->getPairsByProgram(0, 'noclosed');
$executions = $this->project->getStats(0, 'all');
$executions = $this->project->getStats(0, 'all', 0, 0, 30, 'id_desc');
$teams = $this->dao->select('root,account')->from(TABLE_TEAM)
->where('root')->in($this->app->user->view->sprints)
@@ -2012,18 +2047,38 @@ class execution extends control
$statusCount[$status] += isset($kanbanGroup[$projectID][$status]) ? count($kanbanGroup[$projectID][$status]) : 0;
/* Max 5 closed executions. */
/* Max 2 closed executions. */
if($status == 'closed')
{
if(isset($myExecutions[$status]) and count($myExecutions[$status]) >= 5) $myExecutions[$status] = array_slice($myExecutions[$status], 0, 5, true);
if(isset($kanbanGroup[$projectID][$status]) and count($kanbanGroup[$projectID][$status]) >= 5) $kanbanGroup[$projectID][$status] = array_slice($kanbanGroup[$projectID][$status], 0, 5, true);
if(isset($myExecutions[$status]) and count($myExecutions[$status]) > 2)
{
foreach($myExecutions[$status] as $executionID => $execution)
{
unset($myExecutions[$status][$executionID]);
$myExecutions[$status][$execution->closedDate] = $execution;
}
krsort($myExecutions[$status]);
$myExecutions[$status] = array_slice($myExecutions[$status], 0, 2, true);
}
if(isset($kanbanGroup[$projectID][$status]) and count($kanbanGroup[$projectID][$status]) > 2)
{
foreach($kanbanGroup[$projectID][$status] as $executionID => $execution)
{
unset($kanbanGroup[$projectID][$status][$executionID]);
$kanbanGroup[$projectID][$status][$execution->closedDate] = $execution;
}
krsort($kanbanGroup[$projectID][$status]);
$kanbanGroup[$projectID][$status] = array_slice($kanbanGroup[$projectID][$status], 0, 2);
}
}
}
if(empty($kanbanGroup[$projectID])) continue;
$projectCount++;
}
krsort($kanbanGroup);
$this->view->title = $this->lang->execution->executionKanban;
$this->view->kanbanGroup = empty($myExecutions) ? $kanbanGroup : array($myExecutions) + $kanbanGroup;
@@ -2149,6 +2204,14 @@ class execution extends control
}
}
/* Close the page when there is no data. */
$hasData = false;
foreach($datas as $data)
{
if(!empty($data)) $hasData = true;
}
if(!$hasData) die(js::alert($this->lang->execution->noPrintData) . js::close());
$this->execution->saveKanbanData($executionID, $originalDatas);
$hasBurn = $this->post->content == 'all';
@@ -2174,8 +2237,7 @@ class execution extends control
$this->execution->setMenu($executionID);
$execution = $this->execution->getById($executionID);
$this->view->position[] = html::a($this->createLink('execution', 'browse', "executionID=$executionID"), $execution->name);
$this->view->position[] = $this->lang->execution->printKanban;
$this->view->executionID = $executionID;
$this->display();
}
@@ -2501,6 +2563,8 @@ class execution extends control
{
$this->execution->linkStory($objectID);
if($object->type != 'project' and $object->project != 0) $this->execution->linkStory($object->project);
if(isonlybody()) die(js::reload('parent'));
die(js::locate($browseLink));
}
@@ -2976,7 +3040,7 @@ class execution extends control
* @access public
* @return void
*/
public function all($status = 'all', $projectID = 0, $orderBy = 'id_desc', $productID = 0, $recTotal = 0, $recPerPage = 10, $pageID = 1)
public function all($status = 'all', $projectID = 0, $orderBy = 'order_asc', $productID = 0, $recTotal = 0, $recPerPage = 10, $pageID = 1)
{
$this->app->loadLang('my');
$this->app->loadLang('product');
@@ -3220,13 +3284,14 @@ class execution extends control
/**
* Import stories by plan.
*
* @param int $executionID
* @param int $planID
* @param int $productID
* @param int $executionID
* @param int $planID
* @param int $productID
* @param string $fromMethod
* @access public
* @return void
*/
public function importPlanStories($executionID, $planID, $productID = 0)
public function importPlanStories($executionID, $planID, $productID = 0, $fromMethod = 'story')
{
$planStories = $planProducts = array();
$planStory = $this->loadModel('story')->getPlanStories($planID);
@@ -3261,7 +3326,7 @@ class execution extends control
$param = "projectID=$executionID";
}
if($count != 0) echo js::alert(sprintf($this->lang->execution->haveDraft, $count)) . js::locate($this->createLink($moduleName, 'story', $param));
die(js::locate(helper::createLink($moduleName, 'story', $param), 'parent'));
die(js::locate(helper::createLink($moduleName, $fromMethod, $param)));
}
/**
@@ -3347,4 +3412,62 @@ class execution extends control
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->display();
}
/**
*Ajax get group menu of lanes.
*
* @param string $type all|syory|task|bug
* @param string $group
* @access public
* @return void
*/
public function ajaxGetGroup($type, $group = 'default')
{
$this->app->loadLang('kanban');
$groups = array();
$groups = $this->lang->kanban->group->$type;
die(html::select("group", $groups, $group, 'class="form-control chosen" data-max_drop_width="215"'));
}
/**
* Ajax update kanban.
*
* @param int $executionID
* @param string $enterTime
* @param string $browseType
* @param string $groupBy
* @access public
* @return void
*/
public function ajaxUpdateKanban($executionID = 0, $enterTime = '', $browseType = '', $groupBy = '')
{
$enterTime = date('Y-m-d H:i:s', $enterTime);
$lastEditedTime = $this->dao->select("max(lastEditedTime) as lastEditedTime")->from(TABLE_KANBANLANE)->where('execution')->eq($executionID)->fetch('lastEditedTime');
if($lastEditedTime > $enterTime)
{
$kanbanGroup = $this->loadModel('kanban')->getExecutionKanban($executionID, $browseType, $groupBy);
die(json_encode($kanbanGroup));
}
else
{
die('');
}
}
/**
* AJAX: Update the execution name.
*
* @param int $executionID
* @param string $newExecutionName
* @access public
* @return bool
*/
public function ajaxUpdateExecutionName($executionID, $newExecutionName)
{
$this->dao->update(TABLE_EXECUTION)->set('name')->eq($newExecutionName)->where('id')->eq($executionID)->exec();
if(dao::isError()) echo false;
echo true;
}
}
+8 -23
View File
@@ -1,23 +1,8 @@
.main-table .table {cursor: default; border-collapse: unset;}
.boards {display: table; table-layout: fixed; width: 100%; min-width: 140px;}
.board {display: table-cell; width: 25%; padding: 10px;}
.board > div {max-height: 230px; overflow: auto;}
.board:not(:last-child), .board-project {border-right: 2px solid #fff;}
.board-item {border: 1px solid #EBEBEB; padding: 5px 10px; cursor: default; border-radius: 2px; background-color: #fff;}
.board-item:hover {border-color: #ccc;}
.board-item + .board-item {margin-top: 10px;}
#kanban {overflow-y: auto;}
#kanban thead > tr > th:not(:last-child) {border-right: 2px solid #efefef;}
#kanban tbody > tr > td {line-height: 24px;}
#kanban tbody > tr > td {background-color: #F5F5F5;}
#kanban tbody > tr:not(:last-child) > td {border-bottom: 5px solid #fff !important;}
.s-doing .table-row .table-col:last-child, .c-progress {width: 30px; padding-left: 3px; padding-top: 1px;}
.table-row .table-col:first-child, .board-project {overflow: hidden; white-space: nowrap;}
.table-grouped > tbody > tr,
.table-grouped > tbody > tr:hover {background: #fff !important;}
.projectColor {width: 5px; padding: 0px !important; border-right: unset !important}
#kanbanList .panel-body {padding: 10px!important;}
#kanbanList .kanban-header {min-height: 32px!important;}
#kanbanList .kanban-header-col {height: 32px!important; padding: 0!important;}
#kanbanList .kanban-header-col > .title {padding: 0 5px!important;}
#kanbanList .kanban-col[data-type="project"] .kanban-lane-items {height: 100%; display: flex; flex-direction: column; justify-content: center;}
#kanbanList .kanban-lane-name {width: 5px; margin-right: 15px;}
#kanbanList .kanban-lane-name > .text {display: none;}
#kanbanList .kanban-item.link-block > a {cursor: move;}
+42 -62
View File
@@ -1,65 +1,45 @@
.boards {display: table; table-layout: fixed; width: auto; min-height: 50px; min-width: 140px;}
.boards .board:not(:last-child) {border-right: 1px solid #ddd;}
.board {display: table-cell; width: 16.666666667%; padding: 10px; border: 1px solid transparent; transition: background-color .2s, opacity .2s; vertical-align: top;}
.board-item {border: 1px solid #EBEBEB; padding: 5px 10px; cursor: move; border-radius: 2px; background-color: #fff; transition: border .2s, opacity .2s; overflow: hidden;}
.board-item.disabled {cursor: not-allowed;}
.board-item:hover {border-color: #ccc;}
.board-item > .title {line-height: 20px; max-height: 40px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; word-break: break-all;}
.board-item > .info {line-height: 22px; margin-top: 6px;}
.board-item + .board-item {margin-top: 10px;}
.board-item .task-left {float: right; font-size: 12px; color: #a6aab8;}
.boards-wrapper {overflow: auto;}
.board.can-drop-in {background-color: #fff !important; opacity: 1 !important;}
.c-board.dragging {color: #006af1;}
.board.drop-to {background-color: #fff0d5 !important;}
.board-drag-holder {background: #ccc; background: rgba(0, 0, 0, .1); border-radius: 2px; border: 1px solid rgba(0,0,0,.05); display: none;}
.board.drop-to .board-drag-holder {display: block;}
.board-item + .board-drag-holder {margin-top: 10px;}
.board-item.dragging {opacity: .35;}
.board-item .btn {padding: 2px 10px 2px 23px; font-size: 12px; position: relative; left: -2px; height: 24px;}
.board-item .btn-icon-left > .icon {width: 22px; height: 22px; line-height: 20px; font-size: 14px; opacity: 1; top: 1px;}
.board-item .btn-icon-left > span {max-width: 80px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; display: inline-block;}
.board-title {padding-right: 20px;}
.board-actions {position: absolute; right: 3px; top: 3px;}
.board-actions.nav > li > a {padding: 3px 3px;}
#main {padding-bottom: 10px;}
#main > .container {max-width: 1960px!important; padding: 0 10px}
#kanban {overflow-y: auto; min-height: 350px;}
#kanban > .table {min-width: 1100px; table-layout: auto;}
#kanban.dragging .boards.dragging .board {background: #eee; opacity: .35; border-color: #f1f1f1;}
#kanban thead > tr > th {padding-left: 0; padding-right: 0;}
#kanban thead .c-side {padding: 5px; max-width: 15%; min-width: 200px;}
#kanban .label-pri {width: 16px; height: 16px; line-height: 12px; min-width: 16px; font-size: 12px; padding: 0;}
#kanban tbody > tr > td {line-height: 24px;}
#kanban .c-board {border-bottom: 4px #EAF3FC solid; min-width: 140px;}
#kanban .c-board.s-wait {border-color: #7EC5FF;}
#kanban .c-board.s-doing {border-color: #0991FF;}
#kanban .c-board.s-pause {border-color: #fdc137;}
#kanban .c-board.s-done {border-color: #0BD986;}
#kanban .c-board.s-cancel {border-color: #CBD0DB;}
#kanban .c-board.s-closed {border-color: #838A9D;}
#kanban .table-grouped tbody > tr:hover {background: transparent;}
#kanban .c-boards, #kanban td.c-side {border-bottom: 1px solid #eee;}
#kanban .group-info > span + span {display: inline-block; margin-left: 8px;}
#kanban th.c-board {color: #3c4353; font-weight: bold;}
#kanban .fix-table-copy-wrapper {overflow: visible !important;}
#kanban .fix-table-copy-wrapper th.c-board {color: #eee;}
#kanban .fix-table-copy-wrapper th.c-board .btn-link {color: #fff;}
#kanban .group-title {word-break: break-all; line-height: 16px; padding: 3px 0; display: block;}
.kanban + .kanban {margin-top: 15px}
.kanban-item {position: relative;}
.kanban-item > .title { display: block;white-space: nowrap; overflow: hidden; text-overflow: ellipsis}
.kanban-item > .infos {position: relative; margin-top: 5px}
.kanban-item > .infos > .info + .info {margin-left: 8px}
.kanban-item > .infos > .info-id,
.kanban-item > .infos > .info-deadline,
.kanban-item > .infos > .info-estimate {font-size: 12px; position: relative; top: 2px}
.kanban-item > .infos > .label-pri {min-width: 16px; line-height: 14px; height: 16px; padding: 0}
.kanban-item > .infos > .label-severity {transform: scale(.75)}
.kanban-item > .infos > .avatar {position: absolute; right: 0; top: 0}
.kanban-item > .actions {position: absolute; top: 4px; right: 4px; opacity: 0;}
.kanban-item:hover > .actions {opacity: 1;}
.kanban-item > .actions > a {display: block; float: left; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; opacity: .7;}
.kanban-item > .actions > a:hover {background-color: rgba(0,0,0,.075); opacity: 1;}
.table-grouped > tbody > tr,
.table-grouped > tbody > tr:hover {background: #fff !important;}
.kanban-header-col > .actions {padding-top: 22px}
.kanban-header-parent-col .kanban-header-col > .actions {padding-top: 6px; padding-right: 2px;}
.kanban-header-col > .actions > a {display: block; float: left; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; opacity: .7;}
.kanban-header-col > .actions > a:hover {background-color: rgba(0,0,0,.075); opacity: 1;}
.fixedSide {position: fixed; background-color: rgb(75, 75, 75, .85); color: #eee; z-index: 999;}
.fixedSide .dropdown-menu {background-color: rgb(75, 75, 75, .85);}
.fixedSide .dropdown-menu > li > a {color: #eee;}
.fixedSide .btn-link, .fixedSide a , .fixedSide .text-muted {color: #eee;}
.fixedSide .c-board {border-bottom: 4px #EAF3FC solid; min-width: 140px;}
.fixedSide th.c-board {color: #3c4353; font-weight: bold;}
.fixedSide td.c-side {border-bottom: 1px solid #eee;}
.fixedSide thead .c-side {padding: 5px !important; max-width: 15%; min-width: 200px;}
.fixedSide thead > tr > th {padding-left: 0; padding-right: 0;}
.fixedSide tbody > tr > td {line-height: 24px;}
.fixedSide thead > tr > th, .fixedSide tbody > tr > td {min-height: 36px; padding: 2px 8px !important;}
.fixedSide .group-title {word-break: break-all; line-height: 16px; padding: 3px 0; display: block;}
.fixedSide .group-info > span + span {display: inline-block; margin-left: 8px;}
.fixedSide .label-pri {width: 16px; height: 16px; line-height: 12px; min-width: 16px; font-size: 12px; padding: 0;}
.kanban-lane-name > .actions {position: absolute; top: 0; left: 0; right: 0; opacity: 0;}
.kanban-lane-name:hover > .actions {opacity: 1;}
.kanban-lane-name > .actions > a {display: block; width: 20px; height: 20px; line-height: 20px; text-align: center; opacity: .7; color: #fff;}
.kanban-lane-name > .actions > a:hover {background-color: rgba(0,0,0,.2); opacity: 1;}
.kanban-affixed .kanban-header-col > .title > .text,
.kanban-affixed .kanban-header-col > .title > .count {color: #fff!important;}
#kanbanContainer {margin: 0;}
#kanbanContainer > .panel-body {overflow: auto;}
#kanbans .kanban {min-height: initial;}
#kanbans .kanban-lane {min-height: 150px;}
#kanbans .kanban-affixed > .kanban-header {top: 100px;}
#type_chosen .icon-kanban {padding-right: 10px; font-size: 15px;}
.dropdown-menu a {text-align: left;}
.scrollbar-hover {max-height: 2000px; overflow: scroll !important;}
.c-type {width: 150px !important; overflow: unset;}
.c-group {width: 190px !important; overflow: unset;}
.c-type {margin-left: 0px !important;}
+1
View File
@@ -1 +1,2 @@
.c-object {width: 160px;}
.c-branch, .c-estimate {width: 80px;}
+2 -2
View File
@@ -1,10 +1,10 @@
$(function()
{
$('#projectTableList').on('sort.sortable', function(e, data)
$('#executionTableList').on('sort.sortable', function(e, data)
{
var list = '';
for(i = 0; i < data.list.length; i++) list += $(data.list[i].item).attr('data-id') + ',';
$.post(createLink('project', 'updateOrder'), {'projects' : list, 'orderBy' : orderBy});
$.post(createLink('execution', 'updateOrder'), {'executions' : list, 'orderBy' : orderBy});
});
});
+170
View File
@@ -0,0 +1,170 @@
/**
* Process kanban data
* @returns {Object} kanban data
*/
function processKanbanData()
{
/* Generate columns */
var columns = [{id: 'project', type: 'project', name: window.langDoingProject, cardType: 'span'}];
$.each(kanbanColumns, function(type, name)
{
columns.push({id: type, type: type, name: name, cardType: 'execution'});
});
/* Format lanes data */
var lanes = [];
$.each(kanbanGroup, function(projectID, statusMap)
{
var projectName = +projectID ? projectNames[projectID] : langMyExecutions;
var cards = {project: [{id: projectID, name: projectName}]};
$.each(kanbanColumns, function(type)
{
var cardList = [];
var executions = statusMap[type];
if(!executions) return;
$.each(executions, function(index, execution)
{
var executionCard = $.extend({}, execution, {id: projectID + '-' + execution.id, _id: execution.id});
cardList.push(executionCard);
});
cards[type] = cardList;
});
lanes.push({id: projectID, name: projectName, cards: cards});
});
return {id: 'executions', columns: columns, lanes: lanes};
}
/*
* Find drop columns
* @param {JQuery} $element Drag element
* @param {JQuery} $root Dnd root element
*/
function findDropColumns($element, $root)
{
var $col = $element.closest('.kanban-col');
var col = $col.data();
var lane = $col.closest('.kanban-lane').data();
var kanbanID = $root.data('id');
var kanbanRules = window.kanbanDropRules ? window.kanbanDropRules[kanbanID] : null;
if(!kanbanRules) return $root.find('.kanban-lane[data-id="' + lane.id + '"] .kanban-lane-col:not([data-type="project"],[data-type="' + col.type + '"])');
var colRules = kanbanRules[col.type];
var lane = $col.closest('.kanban-lane').data('lane');
return $root.find('.kanban-lane-col').filter(function()
{
if(!colRules) return false;
if(colRules === true) return true;
var $newCol = $(this);
var newCol = $newCol.data();
if(newCol.id === col.id) return false;
var $newLane = $newCol.closest('.kanban-lane');
var newLane = $newLane.data('lane');
return colRules.indexOf(newCol.type) > -1 && newLane.id === lane.id;
});
}
/**
* Change column type for a card
* @param {Object} card Card object
* @param {String} fromColType The column type before change
* @param {String} toColType The column type after change
* @param {String} kanbanID Kanban ID
*/
function changeCardColType(card, fromColType, toColType, kanbanID)
{
if(typeof card == 'undefined') return false;
var cardID = card.id;
var executionID = cardID.substr(cardID.indexOf("-") + 1);;
var showIframe = false;
if(toColType == 'doing')
{
if(fromColType == 'wait' && priv.canStart)
{
var link = createLink('execution', 'start', 'executionID=' + executionID, '', true);
showIframe = true;
}
if((fromColType == 'suspended' || fromColType == 'closed') && priv.canActivate)
{
var link = createLink('execution', 'activate', 'executionID=' + executionID, '', true);
showIframe = true;
}
}
else if(toColType == 'suspended')
{
if((fromColType == 'wait' || fromColType == 'doing') && priv.canSuspend)
{
var link = createLink('execution', 'suspend', 'executionID=' + executionID, '', true);
showIframe = true;
}
}
else if(toColType == 'closed')
{
if(priv.canClose)
{
var link = createLink('execution', 'close', 'executionID=' + executionID, '', true);
showIframe = true;
}
}
if(showIframe)
{
var modalTrigger = new $.zui.ModalTrigger({type: 'iframe', width: '80%', url: link});
modalTrigger.show();
}
/*
// TODO: The server must return a updated kanban data 服务器返回更新后的看板数据
// 调用 updateKanban 更新看板数据
updateKanban(kanbanID, newKanbanData);
*/
}
/**
* Handle finish drop task
* @param {Object} event Event object
* @returns {void}
*/
function handleFinishDrop(event)
{
var $card = $(event.element); // The drag card
var $dragCol = $card.closest('.kanban-lane-col');
var $dropCol = $(event.target);
/* Get d-n-d(drag and drop) infos 获取拖放操作相关信息 */
var card = $card.data('item');
var fromColType = $dragCol.data('type');
var toColType = $dropCol.data('type');
var kanbanID = $card.closest('.kanban').data('id');
changeCardColType(card, fromColType, toColType, kanbanID);
}
$(function()
{
var kanbanGroup = window.kanbanGroup;
if(!kanbanGroup) return;
$('#kanban').kanban(
{
data: processKanbanData(),
// noLaneName: true,
droppable:
{
selector: '.kanban-item:not(.kanban-item-span)',
target: findDropColumns,
finish: handleFinishDrop,
mouseButton: 'left'
},
});
});
File diff suppressed because it is too large Load Diff

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