Merge branch 'master' of https://git.zcorp.cc/easycorp/zentaopms
This commit is contained in:
+54
-54
@@ -14,7 +14,7 @@ CREATE TABLE IF NOT EXISTS `zt_acl` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_action`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_action` (
|
||||
`id` int(9) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`objectType` varchar(30) NOT NULL DEFAULT '',
|
||||
`objectID` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`product` text NULL,
|
||||
@@ -37,8 +37,8 @@ CREATE TABLE IF NOT EXISTS `zt_action` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_api_lib_release`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_api_lib_release` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`lib` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`lib` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`desc` varchar(255) NOT NULL DEFAULT '',
|
||||
`version` varchar(255) NOT NULL DEFAULT '',
|
||||
`snap` mediumtext NULL,
|
||||
@@ -48,10 +48,10 @@ CREATE TABLE IF NOT EXISTS `zt_api_lib_release` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_api`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_api` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`id` int(11) 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,
|
||||
`lib` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`module` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`title` varchar(100) NOT NULL DEFAULT '',
|
||||
`path` varchar(255) NOT NULL DEFAULT '',
|
||||
`protocol` varchar(10) NOT NULL DEFAULT '',
|
||||
@@ -61,7 +61,7 @@ CREATE TABLE IF NOT EXISTS `zt_api` (
|
||||
`status` varchar(20) NOT NULL DEFAULT '',
|
||||
`owner` varchar(30) NOT NULl DEFAULT 0,
|
||||
`desc` mediumtext NULL,
|
||||
`version` smallint UNSIGNED NOT NULL DEFAULT 0,
|
||||
`version` smallint(6) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`params` text NULL,
|
||||
`paramsExample` text NUll,
|
||||
`responseExample` text NUll,
|
||||
@@ -76,9 +76,9 @@ CREATE TABLE IF NOT EXISTS `zt_api` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_apispec`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_apispec` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`doc` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`module` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`doc` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`module` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`title` varchar(100) NOT NULL DEFAULT '',
|
||||
`path` varchar(255) NOT NULL DEFAULT '',
|
||||
`protocol` varchar(10) NOT NULL DEFAULT '',
|
||||
@@ -88,7 +88,7 @@ CREATE TABLE IF NOT EXISTS `zt_apispec` (
|
||||
`status` varchar(20) NOT NULL DEFAULT '',
|
||||
`owner` varchar(255) NOT NULl DEFAULT 0,
|
||||
`desc` mediumtext NULL,
|
||||
`version` smallint UNSIGNED NOT NULL DEFAULT 0,
|
||||
`version` smallint(6) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`params` text NULL,
|
||||
`paramsExample` text NUll,
|
||||
`responseExample` text NUll,
|
||||
@@ -99,12 +99,12 @@ CREATE TABLE IF NOT EXISTS `zt_apispec` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_apistruct`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_apistruct` (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`lib` int UNSIGNED NOT NULL DEFAULT 0,
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`lib` int(11) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`name` varchar(30) NOT NULL DEFAULT '',
|
||||
`type` varchar(50) NOT NULL DEFAULT '',
|
||||
`desc` mediumtext NULL,
|
||||
`version` smallint unsigned NOT NULL DEFAULT 0,
|
||||
`version` smallint(6) unsigned NOT NULL DEFAULT 0,
|
||||
`attribute` text NULL,
|
||||
`addedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`addedDate` datetime NULL,
|
||||
@@ -115,12 +115,12 @@ CREATE TABLE IF NOT EXISTS `zt_apistruct` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_apistruct_spec`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_apistruct_spec` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`id` int(11) 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,
|
||||
`version` smallint(6) unsigned NOT NULL DEFAULT 0,
|
||||
`addedBy` varchar(30) NOT NULL DEFAULT 0,
|
||||
`addedDate` datetime NULL,
|
||||
primary key (`id`)
|
||||
@@ -142,7 +142,7 @@ CREATE TABLE IF NOT EXISTS `zt_approval` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_approvalflow`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_approvalflow` (
|
||||
`id` int(8) NOT NULL AUTO_INCREMENT,
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`code` varchar(100) NOT NULL DEFAULT '',
|
||||
`desc` mediumtext NULL,
|
||||
@@ -243,7 +243,7 @@ CREATE TABLE IF NOT EXISTS `zt_branch` (
|
||||
`desc` varchar(255) NOT NULL DEFAULT '',
|
||||
`createdDate` date NULL,
|
||||
`closedDate` date NULL,
|
||||
`order` smallint unsigned NOT NULL DEFAULT '0',
|
||||
`order` smallint(6) unsigned NOT NULL DEFAULT '0',
|
||||
`deleted` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `product` (`product`)
|
||||
@@ -418,7 +418,7 @@ CREATE TABLE IF NOT EXISTS `zt_casestep` (
|
||||
`id` mediumint(8) unsigned NOT NULL auto_increment,
|
||||
`parent` mediumint(8) unsigned NOT NULL default '0',
|
||||
`case` mediumint(8) unsigned NOT NULL default '0',
|
||||
`version` smallint(3) unsigned NOT NULL default '0',
|
||||
`version` smallint(6) unsigned NOT NULL default '0',
|
||||
`type` varchar(10) NOT NULL DEFAULT 'step',
|
||||
`desc` text NULL,
|
||||
`expect` text NULL,
|
||||
@@ -432,14 +432,14 @@ CREATE TABLE IF NOT EXISTS `zt_cfd` (
|
||||
`execution` int(8) NOT NULL DEFAULT '0',
|
||||
`type` char(30) NOT NULL DEFAULT '',
|
||||
`name` char(30) NOT NULL DEFAULT '',
|
||||
`count` smallint NOT NULL DEFAULT '0',
|
||||
`count` smallint(6) NOT NULL DEFAULT '0',
|
||||
`date` date NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
CREATE UNIQUE INDEX `execution_type_name_date` ON `zt_cfd`(`execution`,`type`,`name`,`date`);
|
||||
-- DROP TABLE IF EXISTS `zt_chart`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_chart` (
|
||||
`id` mediumint unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`dimension` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`type` varchar(30) NOT NULL DEFAULT '',
|
||||
@@ -448,7 +448,7 @@ CREATE TABLE IF NOT EXISTS `zt_chart` (
|
||||
`desc` text NULL,
|
||||
`settings` mediumtext NULL,
|
||||
`filters` mediumtext NULL,
|
||||
`step` tinyint(1) unsigned NOT NULL DEFAULT '0',
|
||||
`step` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`fields` mediumtext NULL,
|
||||
`langs` text NULL,
|
||||
`sql` mediumtext NULL,
|
||||
@@ -459,7 +459,7 @@ CREATE TABLE IF NOT EXISTS `zt_chart` (
|
||||
`createdDate` datetime NULL,
|
||||
`editedBy` varchar(30) NOT NULL DEFAULT '',
|
||||
`editedDate` datetime NULL,
|
||||
`deleted` tinyint NOT NULL DEFAULT '0',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_screen`;
|
||||
@@ -560,25 +560,25 @@ CREATE TABLE `zt_dashboard` (
|
||||
`id` mediumint(8) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`dimension` int(8) NOT NULL default 0,
|
||||
`module` mediumint NOT NULL DEFAULT '0',
|
||||
`module` mediumint(8) NOT NULL DEFAULT '0',
|
||||
`desc` mediumtext NULL,
|
||||
`layout` mediumtext NULL,
|
||||
`filters` mediumtext NULL,
|
||||
`createdBy` varchar(30) NOT NULL DEFAULT '',
|
||||
`createdDate` datetime NULL,
|
||||
`deleted` tinyint NOT NULL DEFAULT '0',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_dataset`;
|
||||
CREATE TABLE `zt_dataset` (
|
||||
`id` mediumint unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(155) NOT NULL DEFAULT '',
|
||||
`sql` text NULL,
|
||||
`fields` mediumtext NULL,
|
||||
`objects` mediumtext NULL,
|
||||
`createdBy` varchar(30) NOT NULL DEFAULT '',
|
||||
`createdDate` datetime NULL,
|
||||
`deleted` tinyint NOT NULL DEFAULT '0',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_dataview`;
|
||||
@@ -596,7 +596,7 @@ CREATE TABLE IF NOT EXISTS `zt_dataview` (
|
||||
`createdDate` datetime NULL,
|
||||
`editedBy` varchar(30) NULL DEFAULT '',
|
||||
`editedDate` datetime NULL,
|
||||
`deleted` tinyint NOT NULL DEFAULT '0',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_dept`;
|
||||
@@ -778,7 +778,7 @@ CREATE TABLE IF NOT EXISTS `zt_entry` (
|
||||
`desc` mediumtext NULL,
|
||||
`createdBy` varchar(30) NOT NULL DEFAULT '',
|
||||
`createdDate` datetime NULL,
|
||||
`calledTime` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`calledTime` int(11) unsigned NOT NULL DEFAULT '0',
|
||||
`editedBy` varchar(30) NOT NULL DEFAULT '',
|
||||
`editedDate` datetime NULL,
|
||||
`deleted` enum('0', '1') NOT NULL DEFAULT '0',
|
||||
@@ -824,7 +824,7 @@ CREATE TABLE IF NOT EXISTS `zt_file` (
|
||||
`pathname` char(100) NOT NULL DEFAULT '',
|
||||
`title` varchar(255) NOT NULL DEFAULT '',
|
||||
`extension` char(30) NOT NULL DEFAULT '',
|
||||
`size` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`size` int(11) unsigned NOT NULL DEFAULT '0',
|
||||
`objectType` char(30) NOT NULL DEFAULT '',
|
||||
`objectID` mediumint(9) NOT NULL DEFAULT '0',
|
||||
`addedBy` char(30) NOT NULL DEFAULT '',
|
||||
@@ -869,7 +869,7 @@ CREATE TABLE IF NOT EXISTS `zt_holiday` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_history`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_history` (
|
||||
`id` int(9) unsigned NOT NULL auto_increment,
|
||||
`id` int(11) unsigned NOT NULL auto_increment,
|
||||
`action` mediumint(8) unsigned NOT NULL default '0',
|
||||
`field` varchar(30) NOT NULL default '',
|
||||
`old` text NULL,
|
||||
@@ -1119,7 +1119,7 @@ CREATE TABLE IF NOT EXISTS `zt_mr` (
|
||||
`sourceBranch` varchar(100) NOT NULL DEFAULT '',
|
||||
`targetProject` varchar(50) NOT NULL DEFAULT '',
|
||||
`targetBranch` varchar(100) NOT NULL DEFAULT '',
|
||||
`mriid` int unsigned NOT NULL DEFAULT '0',
|
||||
`mriid` int(11) unsigned NOT NULL DEFAULT '0',
|
||||
`title` varchar(255) NOT NULL DEFAULT '',
|
||||
`description` text NULL,
|
||||
`assignee` varchar(255) NOT NULL DEFAULT '',
|
||||
@@ -1159,10 +1159,10 @@ CREATE TABLE IF NOT EXISTS `zt_mrapproval` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_notify`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_notify` (
|
||||
`id` mediumint unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`objectType` varchar(50) NOT NULL DEFAULT '',
|
||||
`objectID` mediumint unsigned NOT NULL DEFAULT '0',
|
||||
`action` mediumint NOT NULL DEFAULT '0',
|
||||
`objectID` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`action` mediumint(9) NOT NULL DEFAULT '0',
|
||||
`toList` varchar(255) NOT NULL DEFAULT '',
|
||||
`ccList` text NULL,
|
||||
`subject` varchar(255) NOT NULL DEFAULT '',
|
||||
@@ -1484,7 +1484,7 @@ CREATE TABLE IF NOT EXISTS `zt_repo` (
|
||||
`desc` text NULL,
|
||||
`extra` char(30) NOT NULL DEFAULT '',
|
||||
`preMerge` enum('0','1') COLLATE 'utf8_general_ci' NOT NULL DEFAULT '0',
|
||||
`job` mediumint unsigned NOT NULL DEFAULT '0',
|
||||
`job` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`fileServerUrl` text COLLATE 'utf8_general_ci' NULL,
|
||||
`fileServerAccount` varchar(40) NOT NULL default '',
|
||||
`fileServerPassword` varchar(100) NOT NULL default '',
|
||||
@@ -1502,7 +1502,7 @@ CREATE TABLE IF NOT EXISTS `zt_repobranch` (
|
||||
CREATE UNIQUE INDEX `repo_revision_branch` ON `zt_repobranch`(`repo`,`revision`,`branch`);
|
||||
-- DROP TABLE IF EXISTS `zt_repofiles`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_repofiles` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`repo` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`revision` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`path` varchar(255) NOT NULL DEFAULT '',
|
||||
@@ -1553,7 +1553,7 @@ CREATE TABLE IF NOT EXISTS `zt_searchdict` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_searchindex`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_searchindex` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
|
||||
`objectType` char(20) NOT NULL DEFAULT '',
|
||||
`objectID` mediumint(9) NOT NULL DEFAULT '0',
|
||||
@@ -1889,7 +1889,7 @@ CREATE TABLE IF NOT EXISTS `zt_testsuite` (
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`desc` mediumtext NULL,
|
||||
`type` varchar(20) NOT NULL DEFAULT '',
|
||||
`order` smallint unsigned NOT NULL DEFAULT '0',
|
||||
`order` smallint(6) unsigned NOT NULL DEFAULT '0',
|
||||
`addedBy` char(30) NOT NULL DEFAULT '',
|
||||
`addedDate` datetime NULL,
|
||||
`lastEditedBy` char(30) NOT NULL DEFAULT '',
|
||||
@@ -1992,7 +1992,7 @@ CREATE TABLE IF NOT EXISTS `zt_user` (
|
||||
`visits` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`visions` varchar(20) NOT NULL DEFAULT 'rnd,lite',
|
||||
`ip` char(15) NOT NULL DEFAULT '',
|
||||
`last` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`last` int(11) unsigned NOT NULL DEFAULT '0',
|
||||
`fails` tinyint(5) NOT NULL DEFAULT '0',
|
||||
`locked` datetime NULL,
|
||||
`feedback` enum('0','1') NOT NULL DEFAULT '0',
|
||||
@@ -2397,9 +2397,9 @@ INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_relationoftasks`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_relationoftasks` (
|
||||
`id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT ,
|
||||
`execution` MEDIUMINT(8) UNSIGNED NOT NULL ,
|
||||
`pretask` MEDIUMINT(8) UNSIGNED NOT NULL ,
|
||||
`id` mediumint(8) UNSIGNED NOT NULL AUTO_INCREMENT ,
|
||||
`execution` mediumint(8) UNSIGNED NOT NULL ,
|
||||
`pretask` mediumint(8) UNSIGNED NOT NULL ,
|
||||
`condition` ENUM( 'begin', 'end' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
|
||||
`task` MEDIUMINT( 8 ) UNSIGNED NOT NULL ,
|
||||
`action` ENUM( 'begin', 'end' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
|
||||
@@ -2470,7 +2470,7 @@ CREATE TABLE IF NOT EXISTS `zt_feedback` (
|
||||
`type` char(30) NOT NULL DEFAULT '',
|
||||
`solution` char(30) NOT NULL DEFAULT '',
|
||||
`desc` text NULL,
|
||||
`pri` tinyint unsigned NOT NULL DEFAULT 2,
|
||||
`pri` tinyint(3) unsigned NOT NULL DEFAULT 2,
|
||||
`status` varchar(30) NOT NULL DEFAULT '',
|
||||
`subStatus` varchar(30) NOT NULL default '',
|
||||
`public` enum('0','1') NOT NULL DEFAULT '0',
|
||||
@@ -2518,13 +2518,13 @@ CREATE TABLE IF NOT EXISTS `zt_ticket` (
|
||||
`startedBy` varchar(255) NOT NULL DEFAULT '',
|
||||
`startedDate` datetime NULL,
|
||||
`deadline` date NULL,
|
||||
`pri` tinyint unsigned NOT NULL DEFAULT '0',
|
||||
`pri` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`estimate` float unsigned NOT NULL,
|
||||
`left` float unsigned NOT NULL,
|
||||
`status` varchar(30) NOT NULL DEFAULT '',
|
||||
`openedBy` varchar(30) NOT NULL DEFAULT '',
|
||||
`openedDate` datetime NULL,
|
||||
`activatedCount` int(10) NOT NULL DEFAULT '0',
|
||||
`activatedCount` int(11) NOT NULL DEFAULT '0',
|
||||
`activatedBy` varchar(30) NOT NULL DEFAULT '',
|
||||
`activatedDate` datetime NULL,
|
||||
`closedBy` varchar(30) NOT NULL DEFAULT '',
|
||||
@@ -2559,9 +2559,9 @@ CREATE TABLE IF NOT EXISTS `zt_ticketsource` (
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_ticketrelation`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_ticketrelation` (
|
||||
`id` mediumint unsigned NOT NULL AUTO_INCREMENT,
|
||||
`ticketId` mediumint unsigned NOT NULL DEFAULT '0',
|
||||
`objectId` mediumint NOT NULL DEFAULT '0',
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`ticketId` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`objectId` mediumint(9) NOT NULL DEFAULT '0',
|
||||
`objectType` varchar(100) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ticketId` (`ticketId`)
|
||||
@@ -12632,7 +12632,7 @@ CREATE TABLE IF NOT EXISTS `zt_auditcl` (
|
||||
`type` char(30) NOT NULL DEFAULT '',
|
||||
`title` varchar(255) NOT NULL DEFAULT '',
|
||||
`objectType` char(30) NOT NULL DEFAULT '',
|
||||
`objectID` int(10) NOT NULL DEFAULT '0',
|
||||
`objectID` int(11) NOT NULL DEFAULT '0',
|
||||
`assignedTo` varchar(30) NOT NULL DEFAULT '',
|
||||
`status` varchar(30) NOT NULL DEFAULT '',
|
||||
`createdBy` varchar(30) NOT NULL DEFAULT '',
|
||||
@@ -12919,7 +12919,7 @@ CREATE TABLE IF NOT EXISTS `zt_meeting` (
|
||||
`host` varchar(30) NOT NULL DEFAULT '',
|
||||
`participant` text NULL,
|
||||
`date` date NULL,
|
||||
`room` int NOT NULL DEFAULT '0',
|
||||
`room` int(11) NOT NULL DEFAULT '0',
|
||||
`minutes` text NULL,
|
||||
`minutedBy` varchar(30) NOT NULL DEFAULT '',
|
||||
`minutedDate` datetime NULL,
|
||||
@@ -12938,7 +12938,7 @@ CREATE TABLE IF NOT EXISTS `zt_meetingroom` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`position` varchar(30) NOT NULL DEFAULT '',
|
||||
`seats` int NOT NULL DEFAULT '0',
|
||||
`seats` int(11) NOT NULL DEFAULT '0',
|
||||
`equipment` varchar(255) NOT NULL DEFAULT '',
|
||||
`openTime` varchar(255) NOT NULL DEFAULT '',
|
||||
`createdBy` varchar(30) NOT NULL DEFAULT '',
|
||||
@@ -12955,7 +12955,7 @@ CREATE TABLE IF NOT EXISTS `zt_assetlib` (
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`type` varchar(255) NOT NULL DEFAULT '',
|
||||
`desc` mediumtext NULL,
|
||||
`order` SMALLINT UNSIGNED NOT NULL DEFAULT '0',
|
||||
`order` smallint(6) UNSIGNED NOT NULL DEFAULT '0',
|
||||
`createdBy` varchar(30) NOT NULL DEFAULT '',
|
||||
`createdDate` datetime NULL,
|
||||
`editedBy` varchar(30) NOT NULL DEFAULT '',
|
||||
@@ -14222,7 +14222,7 @@ CREATE TABLE IF NOT EXISTS `zt_pivot` (
|
||||
`objects` mediumtext NULL,
|
||||
`settings` mediumtext NULL,
|
||||
`filters` mediumtext NULL,
|
||||
`step` tinyint(1) unsigned NOT NULL DEFAULT '0',
|
||||
`step` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||
`stage` enum('draft','published') NOT NULL DEFAULT 'draft',
|
||||
`builtin` enum('0', '1') NOT NULL DEFAULT '0',
|
||||
`createdBy` varchar(30) NOT NULL DEFAULT '',
|
||||
|
||||
@@ -221,11 +221,11 @@ class baseControl
|
||||
}
|
||||
elseif(helper::isAjaxRequest())
|
||||
{
|
||||
die(json_encode(array('result' => false, 'message' => $this->lang->error->loginTimeout)));
|
||||
helper::end(json_encode(array('result' => false, 'message' => $this->lang->error->loginTimeout)));
|
||||
}
|
||||
|
||||
$referer = helper::safe64Encode($uri);
|
||||
die(js::locate(helper::createLink('user', 'login', "referer=$referer")));
|
||||
helper::end(js::locate(helper::createLink('user', 'login', "referer=$referer")));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1018,13 +1018,14 @@ class baseControl
|
||||
* 直接输出data数据,通常用于ajax请求中。
|
||||
* Send data directly, for ajax requests.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function send($data, string $type = 'json')
|
||||
{
|
||||
if($type != 'json') die();
|
||||
if($type != 'json') return helper::end();
|
||||
|
||||
$data = (array)$data;
|
||||
|
||||
@@ -1055,7 +1056,7 @@ class baseControl
|
||||
for($i = 0; $i < $obLevel; $i++) ob_end_clean();
|
||||
|
||||
$response = helper::removeUTF8Bom(urldecode(json_encode($data)));
|
||||
die($response);
|
||||
return helper::end($response);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1066,8 +1067,8 @@ class baseControl
|
||||
{
|
||||
if(!empty($data['message'])) echo js::alert($data['message']);
|
||||
$locate = $data['locate'] ?? $_SERVER['HTTP_REFERER'] ?? '';
|
||||
if(!empty($locate)) die(js::locate($locate));
|
||||
die($data['message'] ?? 'success');
|
||||
if(!empty($locate)) return helper::end(js::locate($locate));
|
||||
return helper::end($data['message'] ?? 'success');
|
||||
}
|
||||
|
||||
if(isset($data['result']) and $data['result'] == 'fail')
|
||||
@@ -1078,27 +1079,27 @@ class baseControl
|
||||
{
|
||||
echo js::alert($data['message']);
|
||||
$locate = $data['locate'] ?? $_SERVER['HTTP_REFERER'] ?? '';
|
||||
if (!empty($locate)) die(js::locate($locate));
|
||||
die($data['message'] ?? 'fail');
|
||||
if (!empty($locate)) return helper::end(js::locate($locate));
|
||||
return helper::end($data['message'] ?? 'fail');
|
||||
}
|
||||
|
||||
$message = json_decode(json_encode($data['message']), true);
|
||||
foreach($message as $item => $errors) $message[$item] = implode(',', $errors);
|
||||
die(js::alert(strip_tags(implode('\n', $message))));
|
||||
return helper::end(js::alert(strip_tags(implode('\n', $message))));
|
||||
}
|
||||
die('fail');
|
||||
return helper::end('fail');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return error json
|
||||
*
|
||||
* @param mixed $error
|
||||
* @return void
|
||||
* @author thanatos thanatos915@163.com
|
||||
*/
|
||||
public function sendError($error)
|
||||
{
|
||||
$this->send(array('result' => 'fail', 'message' => $error));
|
||||
return $this->send(array('result' => 'fail', 'message' => $error));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1106,13 +1107,12 @@ class baseControl
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
* @author thanatos thanatos915@163.com
|
||||
*/
|
||||
public function sendSuccess(array $data)
|
||||
{
|
||||
$data['result'] = 'success';
|
||||
if(empty($data['message'])) $data['message'] = $this->lang->saveSuccess;
|
||||
$this->send($data);
|
||||
return $this->send($data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1157,9 +1157,9 @@ class baseControl
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function locate($url)
|
||||
public function locate(string $url)
|
||||
{
|
||||
header("location: $url");
|
||||
exit;
|
||||
helper::end();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,12 +420,15 @@ class baseHelper
|
||||
* 去掉UTF-8 Bom头。
|
||||
* Remove UTF-8 Bom.
|
||||
*
|
||||
* @param string $string
|
||||
* @param string|false $string
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public static function removeUTF8Bom($string)
|
||||
public static function removeUTF8Bom(string|false $string): string
|
||||
{
|
||||
/* The ob_get_clean() will return false if output buffering isn't active. */
|
||||
if(!is_string($string)) return '';
|
||||
|
||||
if(substr($string, 0, 3) == pack('CCC', 239, 187, 191)) return substr($string, 3);
|
||||
return $string;
|
||||
}
|
||||
|
||||
@@ -287,10 +287,11 @@ class helper extends baseHelper
|
||||
}
|
||||
|
||||
/**
|
||||
* 代替 die、exit 函数终止并输出
|
||||
* 代替 die、exit 函数终止并输出。
|
||||
* Instead of die, exit function to terminate and output.
|
||||
*
|
||||
* @param string $content
|
||||
* @return void
|
||||
* @return never
|
||||
*/
|
||||
public static function end(string $content = ''): never
|
||||
{
|
||||
|
||||
+37
-11
@@ -15,14 +15,32 @@ helper::import(dirname(dirname(__FILE__)) . '/base/filter/filter.class.php');
|
||||
class form extends baseFixer
|
||||
{
|
||||
/**
|
||||
* @var object 原始 $_POST 数据。The raw $_POST data.
|
||||
* 原始 $_POST 数据。
|
||||
* The raw $_POST data.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $rawdata;
|
||||
|
||||
/**
|
||||
* 错误信息列表。
|
||||
* Error list.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $errors;
|
||||
|
||||
/**
|
||||
* 构造方法。
|
||||
* The construct function.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->rawdata = (object)$_POST;
|
||||
$this->data = (object)array();
|
||||
$this->errors = array();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,6 +69,11 @@ class form extends baseFixer
|
||||
$this->rawconfig = $config;
|
||||
|
||||
foreach($this->rawconfig as $key => $value) $this->convertField($key, $value);
|
||||
if(!empty($this->errors))
|
||||
{
|
||||
$response = array('result' => 'fail', 'message' => $this->errors);
|
||||
helper::end(json_encode($response));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -77,19 +100,22 @@ class form extends baseFixer
|
||||
*/
|
||||
public function convertField(string $field, array $config)
|
||||
{
|
||||
if(isset($config['required']) && $config['required'] && !isset($this->rawdata->$field))
|
||||
{
|
||||
throw new InvalidArgumentException("Field $field is required");
|
||||
}
|
||||
|
||||
if(isset($config['required']) && !$config['required'] && !isset($config['default']))
|
||||
{
|
||||
throw new InvalidArgumentException("Field $field is not required, but need default value");
|
||||
}
|
||||
global $app;
|
||||
|
||||
if(!isset($config['type']))
|
||||
{
|
||||
throw new InvalidArgumentException("Field $field need defined type");
|
||||
if(!isset($this->errors[$field])) $this->errors[$field] = array();
|
||||
$this->errors[$field][] = "Field '$field' need defined type";
|
||||
}
|
||||
|
||||
if(isset($config['required']) && $config['required'])
|
||||
{
|
||||
if(!isset($config['default']) && (!isset($this->rawdata->$field) || $this->rawdata->$field === ''))
|
||||
{
|
||||
if(!isset($this->errors[$field])) $this->errors[$field] = array();
|
||||
$fieldName = isset($app->lang->{$app->rawModule}->$field) ? $app->lang->{$app->rawModule}->$field : $field;
|
||||
$this->errors[$field][] = sprintf($lang->error->notempty, $fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($this->rawdata->$field))
|
||||
|
||||
+107
-103
@@ -47,7 +47,7 @@ $config->block->params['default']->count['name'] = $lang->block->count;
|
||||
$config->block->params['default']->count['default'] = 20;
|
||||
$config->block->params['default']->count['control'] = 'input';
|
||||
|
||||
$config->block->params['task'] = clone $config->block->params['default'];
|
||||
$config->block->params['task'] = new stdclass();
|
||||
$config->block->params['task']->type['name'] = $lang->block->type;
|
||||
$config->block->params['task']->type['options'] = $lang->block->typeList->task;
|
||||
$config->block->params['task']->type['control'] = 'select';
|
||||
@@ -55,8 +55,9 @@ $config->block->params['task']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['task']->orderBy['default'] = 'id_desc';
|
||||
$config->block->params['task']->orderBy['options'] = $lang->block->orderByList->task;
|
||||
$config->block->params['task']->orderBy['control'] = 'select';
|
||||
$config->block->params['task']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['bug'] = clone $config->block->params['default'];
|
||||
$config->block->params['bug'] = new stdclass();
|
||||
$config->block->params['bug']->type['name'] = $lang->block->type;
|
||||
$config->block->params['bug']->type['options'] = $lang->block->typeList->bug;
|
||||
$config->block->params['bug']->type['control'] = 'select';
|
||||
@@ -64,8 +65,9 @@ $config->block->params['bug']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['bug']->orderBy['default'] = 'id_desc';
|
||||
$config->block->params['bug']->orderBy['options'] = $lang->block->orderByList->bug;
|
||||
$config->block->params['bug']->orderBy['control'] = 'select';
|
||||
$config->block->params['bug']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['case'] = clone $config->block->params['default'];
|
||||
$config->block->params['case'] = new stdclass();
|
||||
$config->block->params['case']->type['name'] = $lang->block->type;
|
||||
$config->block->params['case']->type['options'] = $lang->block->typeList->case;
|
||||
$config->block->params['case']->type['control'] = 'select';
|
||||
@@ -73,13 +75,15 @@ $config->block->params['case']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['case']->orderBy['default'] = 'id_desc';
|
||||
$config->block->params['case']->orderBy['options'] = $lang->block->orderByList->case;
|
||||
$config->block->params['case']->orderBy['control'] = 'select';
|
||||
$config->block->params['case']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['testtask'] = clone $config->block->params['default'];
|
||||
$config->block->params['testtask']->type['name'] = $lang->block->type;
|
||||
$config->block->params['testtask']->type['options'] = $lang->block->typeList->testtask;
|
||||
$config->block->params['testtask']->type['control'] = 'select';
|
||||
$config->block->params['testtask'] = new stdclass();
|
||||
$config->block->params['testtask']->type['name'] = $lang->block->type;
|
||||
$config->block->params['testtask']->type['options'] = $lang->block->typeList->testtask;
|
||||
$config->block->params['testtask']->type['control'] = 'select';
|
||||
$config->block->params['testtask']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['story'] = clone $config->block->params['default'];
|
||||
$config->block->params['story'] = new stdclass();;
|
||||
$config->block->params['story']->type['name'] = $lang->block->type;
|
||||
$config->block->params['story']->type['options'] = $lang->block->typeList->story;
|
||||
$config->block->params['story']->type['control'] = 'select';
|
||||
@@ -87,153 +91,169 @@ $config->block->params['story']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['story']->orderBy['default'] = 'id_desc';
|
||||
$config->block->params['story']->orderBy['options'] = $lang->block->orderByList->story;
|
||||
$config->block->params['story']->orderBy['control'] = 'select';
|
||||
$config->block->params['story']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['plan'] = clone $config->block->params['default'];
|
||||
$config->block->params['plan'] = $config->block->params['default'];
|
||||
|
||||
$config->block->params['release'] = clone $config->block->params['default'];
|
||||
$config->block->params['release'] = $config->block->params['default'];
|
||||
|
||||
$config->block->params['project'] = clone $config->block->params['default'];
|
||||
$config->block->params['project'] = new stdclass();
|
||||
$config->block->params['project']->type['name'] = $lang->block->type;
|
||||
$config->block->params['project']->type['options'] = $lang->block->typeList->projectAll;
|
||||
$config->block->params['project']->type['control'] = 'select';
|
||||
$config->block->params['project']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['project']->orderBy['options'] = $lang->block->orderByList->product;
|
||||
$config->block->params['project']->orderBy['control'] = 'select';
|
||||
$config->block->params['project']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['projectteam'] = clone $config->block->params['default'];
|
||||
$config->block->params['projectteam'] = new stdclass();
|
||||
$config->block->params['projectteam']->type['name'] = $lang->block->type;
|
||||
$config->block->params['projectteam']->type['options'] = $lang->block->typeList->projectAll;
|
||||
$config->block->params['projectteam']->type['control'] = 'select';
|
||||
$config->block->params['projectteam']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['projectteam']->orderBy['options'] = $lang->block->orderByList->project;
|
||||
$config->block->params['projectteam']->orderBy['control'] = 'select';
|
||||
$config->block->params['projectteam']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['build'] = clone $config->block->params['default'];
|
||||
$config->block->params['build'] = $config->block->params['default'];
|
||||
|
||||
$config->block->params['product'] = clone $config->block->params['default'];
|
||||
$config->block->params['product'] = new stdclass();
|
||||
$config->block->params['product']->type['name'] = $lang->block->type;
|
||||
$config->block->params['product']->type['options'] = $lang->block->typeList->product;
|
||||
$config->block->params['product']->type['control'] = 'select';
|
||||
$config->block->params['product']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['productstatistic'] = clone $config->block->params['default'];
|
||||
$config->block->params['productstatistic'] = new stdclass();
|
||||
$config->block->params['productstatistic']->type['name'] = $lang->block->type;
|
||||
$config->block->params['productstatistic']->type['options'] = $lang->block->typeList->product;
|
||||
$config->block->params['productstatistic']->type['control'] = 'select';
|
||||
$config->block->params['productstatistic']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['projectstatistic'] = clone $config->block->params['default'];
|
||||
$config->block->params['projectstatistic'] = new stdclass();
|
||||
$config->block->params['projectstatistic']->type['name'] = $lang->block->type;
|
||||
$config->block->params['projectstatistic']->type['options'] = $lang->block->typeList->project;
|
||||
$config->block->params['projectstatistic']->type['control'] = 'select';
|
||||
$config->block->params['projectstatistic']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['executionstatistic'] = clone $config->block->params['default'];
|
||||
$config->block->params['executionstatistic'] = new stdclass();
|
||||
$config->block->params['executionstatistic']->type['name'] = $lang->block->type;
|
||||
$config->block->params['executionstatistic']->type['options'] = $lang->block->typeList->execution;
|
||||
$config->block->params['executionstatistic']->type['control'] = 'select';
|
||||
$config->block->params['executionstatistic']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['qaStatistic'] = clone $config->block->params['default'];
|
||||
$config->block->params['qaStatistic']->type['name'] = $lang->block->type;
|
||||
$config->block->params['qaStatistic']->type['options'] = $lang->block->typeList->product;
|
||||
$config->block->params['qaStatistic']->type['control'] = 'select';
|
||||
$config->block->params['qastatistic'] = new stdclass();
|
||||
$config->block->params['qastatistic']->type['name'] = $lang->block->type;
|
||||
$config->block->params['qastatistic']->type['options'] = $lang->block->typeList->product;
|
||||
$config->block->params['qastatistic']->type['control'] = 'select';
|
||||
$config->block->params['qastatistic']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['waterfallissue'] = clone $config->block->params['default'];
|
||||
$config->block->params['waterfallissue'] = new stdclass();
|
||||
$config->block->params['waterfallissue']->type['name'] = $lang->block->type;
|
||||
$config->block->params['waterfallissue']->type['options'] = $lang->block->typeList->issue;
|
||||
$config->block->params['waterfallissue']->type['control'] = 'select';
|
||||
$config->block->params['waterfallissue']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['waterfallissue']->orderBy['options'] = $lang->block->orderByList->product;
|
||||
$config->block->params['waterfallissue']->orderBy['control'] = 'select';
|
||||
$config->block->params['waterfallissue']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['waterfallRisk'] = clone $config->block->params['default'];
|
||||
$config->block->params['waterfallRisk']->type['name'] = $lang->block->type;
|
||||
$config->block->params['waterfallRisk']->type['options'] = $lang->block->typeList->risk;
|
||||
$config->block->params['waterfallRisk']->type['control'] = 'select';
|
||||
$config->block->params['waterfallRisk']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['waterfallRisk']->orderBy['options'] = $lang->block->orderByList->product;
|
||||
$config->block->params['waterfallRisk']->orderBy['control'] = 'select';
|
||||
$config->block->params['waterfallrisk'] = new stdclass();
|
||||
$config->block->params['waterfallrisk']->type['name'] = $lang->block->type;
|
||||
$config->block->params['waterfallrisk']->type['options'] = $lang->block->typeList->risk;
|
||||
$config->block->params['waterfallrisk']->type['control'] = 'select';
|
||||
$config->block->params['waterfallrisk']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['waterfallrisk']->orderBy['options'] = $lang->block->orderByList->product;
|
||||
$config->block->params['waterfallrisk']->orderBy['control'] = 'select';
|
||||
$config->block->params['waterfallrisk']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['scrumIssue'] = clone $config->block->params['default'];
|
||||
$config->block->params['scrumIssue']->type['name'] = $lang->block->type;
|
||||
$config->block->params['scrumIssue']->type['options'] = $lang->block->typeList->issue;
|
||||
$config->block->params['scrumIssue']->type['control'] = 'select';
|
||||
$config->block->params['scrumIssue']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['scrumIssue']->orderBy['options'] = $lang->block->orderByList->product;
|
||||
$config->block->params['scrumIssue']->orderBy['control'] = 'select';
|
||||
$config->block->params['scrumissue'] = new stdclass();
|
||||
$config->block->params['scrumissue']->type['name'] = $lang->block->type;
|
||||
$config->block->params['scrumissue']->type['options'] = $lang->block->typeList->issue;
|
||||
$config->block->params['scrumissue']->type['control'] = 'select';
|
||||
$config->block->params['scrumissue']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['scrumissue']->orderBy['options'] = $lang->block->orderByList->product;
|
||||
$config->block->params['scrumissue']->orderBy['control'] = 'select';
|
||||
$config->block->params['scrumissue']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['scrumRisk'] = clone $config->block->params['default'];
|
||||
$config->block->params['scrumRisk']->type['name'] = $lang->block->type;
|
||||
$config->block->params['scrumRisk']->type['options'] = $lang->block->typeList->risk;
|
||||
$config->block->params['scrumRisk']->type['control'] = 'select';
|
||||
$config->block->params['scrumRisk']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['scrumRisk']->orderBy['options'] = $lang->block->orderByList->product;
|
||||
$config->block->params['scrumRisk']->orderBy['control'] = 'select';
|
||||
$config->block->params['scrumrisk'] = new stdclass();
|
||||
$config->block->params['scrumrisk']->type['name'] = $lang->block->type;
|
||||
$config->block->params['scrumrisk']->type['options'] = $lang->block->typeList->risk;
|
||||
$config->block->params['scrumrisk']->type['control'] = 'select';
|
||||
$config->block->params['scrumrisk']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['scrumrisk']->orderBy['options'] = $lang->block->orderByList->product;
|
||||
$config->block->params['scrumrisk']->orderBy['control'] = 'select';
|
||||
$config->block->params['scrumrisk']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['execution'] = clone $config->block->params['default'];
|
||||
$config->block->params['execution']->type['name'] = $lang->block->type;
|
||||
$config->block->params['execution']->type['options'] = $lang->block->typeList->execution;
|
||||
$config->block->params['execution']->type['control'] = 'select';
|
||||
$config->block->params['execution'] = new stdclass();
|
||||
$config->block->params['execution']->type['name'] = $lang->block->type;
|
||||
$config->block->params['execution']->type['options'] = $lang->block->typeList->execution;
|
||||
$config->block->params['execution']->type['control'] = 'select';
|
||||
$config->block->params['execution']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['assignToMe'] = new stdclass();
|
||||
$config->block->params['assignToMe']->todoCount['name'] = $this->lang->block->todoCount;
|
||||
$config->block->params['assignToMe']->todoCount['default'] = 20;
|
||||
$config->block->params['assignToMe']->todoCount['control'] = 'input';
|
||||
$config->block->params['assignToMe']->taskCount['name'] = $this->lang->block->taskCount;
|
||||
$config->block->params['assignToMe']->taskCount['default'] = 20;
|
||||
$config->block->params['assignToMe']->taskCount['control'] = 'input';
|
||||
$config->block->params['assignToMe']->bugCount['name'] = $this->lang->block->bugCount;
|
||||
$config->block->params['assignToMe']->bugCount['default'] = 20;
|
||||
$config->block->params['assignToMe']->bugCount['control'] = 'input';
|
||||
$config->block->params['assigntome'] = new stdclass();
|
||||
$config->block->params['assigntome']->todoCount['name'] = $this->lang->block->todoCount;
|
||||
$config->block->params['assigntome']->todoCount['default'] = 20;
|
||||
$config->block->params['assigntome']->todoCount['control'] = 'input';
|
||||
$config->block->params['assigntome']->taskCount['name'] = $this->lang->block->taskCount;
|
||||
$config->block->params['assigntome']->taskCount['default'] = 20;
|
||||
$config->block->params['assigntome']->taskCount['control'] = 'input';
|
||||
$config->block->params['assigntome']->bugCount['name'] = $this->lang->block->bugCount;
|
||||
$config->block->params['assigntome']->bugCount['default'] = 20;
|
||||
$config->block->params['assigntome']->bugCount['control'] = 'input';
|
||||
if($config->edition == 'max')
|
||||
{
|
||||
if(helper::hasFeature('risk'))
|
||||
{
|
||||
$config->block->params['assignToMe']->riskCount['name'] = $this->lang->block->riskCount;
|
||||
$config->block->params['assignToMe']->riskCount['default'] = 20;
|
||||
$config->block->params['assignToMe']->riskCount['control'] = 'input';
|
||||
$config->block->params['assigntome']->riskCount['name'] = $this->lang->block->riskCount;
|
||||
$config->block->params['assigntome']->riskCount['default'] = 20;
|
||||
$config->block->params['assigntome']->riskCount['control'] = 'input';
|
||||
}
|
||||
|
||||
if(helper::hasFeature('issue'))
|
||||
{
|
||||
$config->block->params['assignToMe']->issueCount['name'] = $this->lang->block->issueCount;
|
||||
$config->block->params['assignToMe']->issueCount['default'] = 20;
|
||||
$config->block->params['assignToMe']->issueCount['control'] = 'input';
|
||||
$config->block->params['assigntome']->issueCount['name'] = $this->lang->block->issueCount;
|
||||
$config->block->params['assigntome']->issueCount['default'] = 20;
|
||||
$config->block->params['assigntome']->issueCount['control'] = 'input';
|
||||
}
|
||||
|
||||
if(helper::hasFeature('meeting'))
|
||||
{
|
||||
$config->block->params['assignToMe']->meetingCount['name'] = $this->lang->block->meetingCount;
|
||||
$config->block->params['assignToMe']->meetingCount['default'] = 20;
|
||||
$config->block->params['assignToMe']->meetingCount['control'] = 'input';
|
||||
$config->block->params['assigntome']->meetingCount['name'] = $this->lang->block->meetingCount;
|
||||
$config->block->params['assigntome']->meetingCount['default'] = 20;
|
||||
$config->block->params['assigntome']->meetingCount['control'] = 'input';
|
||||
}
|
||||
|
||||
$config->block->params['assignToMe']->feedbackCount['name'] = $this->lang->block->feedbackCount;
|
||||
$config->block->params['assignToMe']->feedbackCount['default'] = 20;
|
||||
$config->block->params['assignToMe']->feedbackCount['control'] = 'input';
|
||||
$config->block->params['assigntome']->feedbackCount['name'] = $this->lang->block->feedbackCount;
|
||||
$config->block->params['assigntome']->feedbackCount['default'] = 20;
|
||||
$config->block->params['assigntome']->feedbackCount['control'] = 'input';
|
||||
}
|
||||
|
||||
$config->block->params['assignToMe']->storyCount['name'] = $this->lang->block->storyCount;
|
||||
$config->block->params['assignToMe']->storyCount['default'] = 20;
|
||||
$config->block->params['assignToMe']->storyCount['control'] = 'input';
|
||||
$config->block->params['assignToMe']->reviewCount['name'] = $this->lang->block->reviewCount;
|
||||
$config->block->params['assignToMe']->reviewCount['default'] = 20;
|
||||
$config->block->params['assignToMe']->reviewCount['control'] = 'input';
|
||||
$config->block->params['assigntome']->storyCount['name'] = $this->lang->block->storyCount;
|
||||
$config->block->params['assigntome']->storyCount['default'] = 20;
|
||||
$config->block->params['assigntome']->storyCount['control'] = 'input';
|
||||
$config->block->params['assigntome']->reviewCount['name'] = $this->lang->block->reviewCount;
|
||||
$config->block->params['assigntome']->reviewCount['default'] = 20;
|
||||
$config->block->params['assigntome']->reviewCount['control'] = 'input';
|
||||
$config->block->params['assigntome']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['scrumTest'] = clone $config->block->params['default'];
|
||||
$config->block->params['scrumTest']->type['name'] = $lang->block->type;
|
||||
$config->block->params['scrumTest']->type['options'] = $lang->block->typeList->testtask;
|
||||
$config->block->params['scrumTest']->type['control'] = 'select';
|
||||
$config->block->params['scrumtest'] = new stdclass();
|
||||
$config->block->params['scrumtest']->type['name'] = $lang->block->type;
|
||||
$config->block->params['scrumtest']->type['options'] = $lang->block->typeList->testtask;
|
||||
$config->block->params['scrumtest']->type['control'] = 'select';
|
||||
$config->block->params['scrumtest']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['scrumList'] = clone $config->block->params['default'];
|
||||
$config->block->params['scrumList']->type['name'] = $lang->block->type;
|
||||
$config->block->params['scrumList']->type['options'] = $lang->block->typeList->scrum;
|
||||
$config->block->params['scrumList']->type['control'] = 'select';
|
||||
$config->block->params['scrumlist'] = new stdclass();
|
||||
$config->block->params['scrumlist']->type['name'] = $lang->block->type;
|
||||
$config->block->params['scrumlist']->type['options'] = $lang->block->typeList->scrum;
|
||||
$config->block->params['scrumlist']->type['control'] = 'select';
|
||||
$config->block->params['scrumlist']->count = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['scrumProduct'] = clone $config->block->params['default'];
|
||||
$config->block->params['scrumProduct'] = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['projectDynamic'] = clone $config->block->params['default'];
|
||||
$config->block->params['projectDynamic'] = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['productDoc'] = clone $config->block->params['default'];
|
||||
$config->block->params['productDoc'] = $config->block->params['default']->count;
|
||||
|
||||
$config->block->params['projectDoc'] = clone $config->block->params['default'];
|
||||
$config->block->params['projectDoc'] = $config->block->params['default']->count;
|
||||
|
||||
$config->block->modules['project'] = new stdclass();
|
||||
$config->block->modules['project']->moreLinkList = new stdclass();
|
||||
@@ -279,19 +299,3 @@ $config->block->modules['doc']->moreLinkList = new stdclass();
|
||||
$config->block->modules['doc']->moreLinkList->docmycollection = 'doc|myspace|type=collect&libID=0&moduleID=0&browseType=all¶m=0&orderBy=editedDate_desc';
|
||||
$config->block->modules['doc']->moreLinkList->productdoc = 'doc|productspace|';
|
||||
$config->block->modules['doc']->moreLinkList->projectdoc = 'doc|projectspace|';
|
||||
|
||||
$config->block->form = new stdclass();
|
||||
$config->block->form->create = array();
|
||||
$config->block->form->create['module'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->block->form->create['code'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->block->form->create['title'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->block->form->create['grid'] = array('type' => 'int', 'required' => false, 'default' => '4');
|
||||
$config->block->form->create['hidden'] = array('type' => 'int', 'required' => false, 'default' => '0');
|
||||
$config->block->form->create['params'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
|
||||
$config->block->form->edit = array();
|
||||
$config->block->form->edit['module'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->block->form->edit['code'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->block->form->edit['title'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->block->form->edit['grid'] = array('type' => 'int', 'required' => false, 'default' => '4');
|
||||
$config->block->form->edit['params'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
$config->block->create = new stdclass();
|
||||
$config->block->create->requiredFields = 'module,code,title';
|
||||
|
||||
$config->block->edit = new stdclass();
|
||||
$config->block->edit->requiredFields = 'module,code,title';
|
||||
|
||||
$config->block->form = new stdclass();
|
||||
$config->block->form->create = array();
|
||||
$config->block->form->create['module'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->block->form->create['code'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->block->form->create['title'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->block->form->create['grid'] = array('type' => 'int', 'required' => false, 'default' => '4');
|
||||
$config->block->form->create['hidden'] = array('type' => 'int', 'required' => false, 'default' => '0');
|
||||
$config->block->form->create['params'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
|
||||
$config->block->form->edit = array();
|
||||
$config->block->form->edit['module'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->block->form->edit['code'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->block->form->edit['title'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->block->form->edit['grid'] = array('type' => 'int', 'required' => false, 'default' => '4');
|
||||
$config->block->form->edit['params'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
@@ -47,7 +47,7 @@ class block extends control
|
||||
|
||||
$this->block->create($formData);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true, 'callback' => 'loadCurrentPage()'));
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true));
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->block->createBlock;
|
||||
@@ -80,7 +80,7 @@ class block extends control
|
||||
|
||||
$this->block->update($formData);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true, 'callback' => 'loadCurrentPage()'));
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true));
|
||||
}
|
||||
|
||||
$block = $this->block->getByID($blockID);
|
||||
|
||||
@@ -4,5 +4,5 @@ function getForm(event)
|
||||
const module = $('#module').val();
|
||||
const code = field == 'module' ? '' : $('#code').val();
|
||||
const url = $.createLink('block', 'create', 'dashboard='+ dashboard +'&module=' + module + '&code=' + (code ? code : ''));
|
||||
loadPage(url, '#codeRow, #paramsRow');
|
||||
loadPage(url, '#codesRow, #paramsRow');
|
||||
}
|
||||
|
||||
@@ -23,10 +23,9 @@ $lang->block->estimate = 'Estimate';
|
||||
$lang->block->last = 'Last';
|
||||
|
||||
$lang->block->account = 'Konto';
|
||||
$lang->block->module = 'Modul';
|
||||
$lang->block->title = 'Titel';
|
||||
$lang->block->source = 'Source module';
|
||||
$lang->block->block = 'Source block';
|
||||
$lang->block->module = 'Modul';
|
||||
$lang->block->code = 'InfoBlock';
|
||||
$lang->block->order = 'Sortierung';
|
||||
$lang->block->height = 'Höhe';
|
||||
$lang->block->role = 'Rolle';
|
||||
|
||||
@@ -23,10 +23,9 @@ $lang->block->estimate = 'Estimate';
|
||||
$lang->block->last = 'Last';
|
||||
|
||||
$lang->block->account = 'Account';
|
||||
$lang->block->module = 'Module';
|
||||
$lang->block->title = 'Title';
|
||||
$lang->block->source = 'Source Module';
|
||||
$lang->block->block = 'Source Block';
|
||||
$lang->block->module = 'Module';
|
||||
$lang->block->code = 'Block';
|
||||
$lang->block->order = 'Order';
|
||||
$lang->block->height = 'Height';
|
||||
$lang->block->role = 'Role';
|
||||
|
||||
@@ -23,10 +23,9 @@ $lang->block->estimate = 'Estimate';
|
||||
$lang->block->last = 'Last';
|
||||
|
||||
$lang->block->account = 'Compte';
|
||||
$lang->block->module = 'Module';
|
||||
$lang->block->title = 'Titre';
|
||||
$lang->block->source = 'Source Module';
|
||||
$lang->block->block = 'Source Bloc';
|
||||
$lang->block->module = 'Module';
|
||||
$lang->block->code = 'Bloc';
|
||||
$lang->block->order = 'Ordre';
|
||||
$lang->block->height = 'Hauteur';
|
||||
$lang->block->role = 'Rôle';
|
||||
|
||||
@@ -21,10 +21,9 @@ $lang->block->estimate = 'Estimate';
|
||||
$lang->block->last = 'Last';
|
||||
|
||||
$lang->block->account = 'Tài khoản';
|
||||
$lang->block->module = 'Module';
|
||||
$lang->block->title = 'Tiêu đề';
|
||||
$lang->block->source = 'Nguồn Module';
|
||||
$lang->block->block = 'Nguồn Block';
|
||||
$lang->block->module = 'Module';
|
||||
$lang->block->code = 'Block';
|
||||
$lang->block->order = 'Sắp xếp';
|
||||
$lang->block->height = 'Chiều cao';
|
||||
$lang->block->role = 'Vai trò';
|
||||
|
||||
@@ -23,10 +23,9 @@ $lang->block->estimate = '预计工时';
|
||||
$lang->block->last = '近期';
|
||||
|
||||
$lang->block->account = '所属用户';
|
||||
$lang->block->module = '所属模块';
|
||||
$lang->block->title = '区块名称';
|
||||
$lang->block->source = '来源模块';
|
||||
$lang->block->block = '来源区块';
|
||||
$lang->block->module = '所属模块';
|
||||
$lang->block->code = '区块';
|
||||
$lang->block->order = '排序';
|
||||
$lang->block->height = '高度';
|
||||
$lang->block->role = '角色';
|
||||
|
||||
+11
-70
@@ -120,51 +120,6 @@ class blockModel extends model
|
||||
return $this->blockTao->fetchMyBlocks($dashboard, $hidden = 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get block json that user can add.
|
||||
* 获取允许用户添加的区块列表.
|
||||
*
|
||||
* @param string $dashboard
|
||||
* @param string $module
|
||||
* @access public
|
||||
* @return string[]
|
||||
*/
|
||||
public function getAvailableBlocks(string $dashboard, string $module = ''): array
|
||||
{
|
||||
if($dashboard == 'my')
|
||||
{
|
||||
if($module and isset($this->lang->block->modules[$module]))
|
||||
{
|
||||
$blocks = $this->lang->block->modules[$module]->availableBlocks;
|
||||
}
|
||||
else
|
||||
{
|
||||
$blocks = array();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($dashboard and isset($this->lang->block->modules[$dashboard]))
|
||||
{
|
||||
$blocks = $this->lang->block->modules[$dashboard]->availableBlocks;
|
||||
}
|
||||
else
|
||||
{
|
||||
$blocks = $this->lang->block->availableBlocks;
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($this->config->block->closed))
|
||||
{
|
||||
foreach($blocks as $blockKey => $blockName)
|
||||
{
|
||||
if(strpos(",{$this->config->block->closed},", ",{$module}|{$blockKey},") !== false) unset($blocks[$blockKey]);
|
||||
}
|
||||
}
|
||||
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get max order number by block dashboard.
|
||||
* 获取对应仪表盘下区块的最大排序号.
|
||||
@@ -175,31 +130,12 @@ class blockModel extends model
|
||||
*/
|
||||
public function getMaxOrderByDashboard(string $dashboard): int
|
||||
{
|
||||
return $this->blockTao->fetchMaxOrderByDashboard($dashboard);
|
||||
}
|
||||
$order = $this->dao->select('MAX(`order`) as `order`')->from(TABLE_BLOCK)
|
||||
->where('dashboard')->eq($dashboard)
|
||||
->andWhere('account')->eq($this->app->user->account)
|
||||
->fetch('order');
|
||||
|
||||
/**
|
||||
* Get block set form params.
|
||||
* 获取不同区块所需的参数配置.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $module
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getParams(string $code, string $module): string
|
||||
{
|
||||
if($code == 'todo' || $code == 'list')
|
||||
{
|
||||
$code = $module;
|
||||
}
|
||||
elseif($code == 'statistic')
|
||||
{
|
||||
$code = $module . $code;
|
||||
}
|
||||
|
||||
$params = zget($this->config->block->params, $code, '');
|
||||
return json_encode($params);
|
||||
return (int)$order;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -346,7 +282,12 @@ class blockModel extends model
|
||||
*/
|
||||
public function update(object $formData): int|false
|
||||
{
|
||||
$this->dao->update(TABLE_BLOCK)->data($formData)->where('id')->eq($formData->id)->autoCheck()->exec();
|
||||
$this->dao->update(TABLE_BLOCK)->data($formData)
|
||||
->where('id')->eq($formData->id)
|
||||
->autoCheck()
|
||||
->batchCheck($this->config->block->edit->requiredFields, 'notempty')
|
||||
->exec();
|
||||
|
||||
if(dao::isError()) return false;
|
||||
|
||||
$this->loadModel('score')->create('block', 'set');
|
||||
|
||||
+5
-19
@@ -2,24 +2,6 @@
|
||||
declare(strict_types=1);
|
||||
class blockTao extends blockModel
|
||||
{
|
||||
/**
|
||||
* Get max order number by block dashboard.
|
||||
* 获取对应仪表盘下区块的最大排序号.
|
||||
*
|
||||
* @param string $module
|
||||
* @access protected
|
||||
* @return int
|
||||
*/
|
||||
protected function fetchMaxOrderByDashboard(string $dashboard): int
|
||||
{
|
||||
$order = $this->dao->select('MAX(`order`) as `order`')->from(TABLE_BLOCK)
|
||||
->where('dashboard')->eq($dashboard)
|
||||
->andWhere('account')->eq($this->app->user->account)
|
||||
->fetch('order');
|
||||
|
||||
return (int)$order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get block list of current user.
|
||||
* 获取当前用户的区块列表.
|
||||
@@ -49,7 +31,11 @@ class blockTao extends blockModel
|
||||
*/
|
||||
protected function insert($formData): bool
|
||||
{
|
||||
$this->dao->insert(TABLE_BLOCK)->data($formData)->autoCheck()->exec();
|
||||
$this->dao->insert(TABLE_BLOCK)->data($formData)
|
||||
->autoCheck()
|
||||
->batchCheck($this->config->block->create->requiredFields, 'notempty')
|
||||
->exec();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,16 +15,17 @@ set::title($title);
|
||||
jsVar('dashboard', $dashboard);
|
||||
|
||||
$paramsRows = array();
|
||||
$isMyDashboard = $dashboard == 'my';
|
||||
$showModules = ($dashboard == 'my' and $modules);
|
||||
$showCodes = (($showModules and $module and $codes) or $dashboard != 'my');
|
||||
|
||||
foreach($params as $key => $row)
|
||||
{
|
||||
$paramsRows[] = formGroup
|
||||
(
|
||||
set::label($row['name']),
|
||||
set::name('params'),
|
||||
set::name("params[$key]"),
|
||||
set::class('form-row'),
|
||||
set::value($block->params->{$key}),
|
||||
set::value(zget($row, 'default', '')),
|
||||
set::control(array
|
||||
(
|
||||
'type' => $row['control'],
|
||||
@@ -39,58 +40,59 @@ form
|
||||
on::change('#code', 'getForm'),
|
||||
formGroup
|
||||
(
|
||||
set::class($isMyDashboard ? '' : 'hidden'),
|
||||
set::value($isMyDashboard ? '' : $dashboard),
|
||||
set::class($showModules ? '' : 'hidden'),
|
||||
set::value($showModules ? $block : $dashboard),
|
||||
set::label($lang->block->lblModule),
|
||||
set::name('module'),
|
||||
set::control(array
|
||||
set::control($showModules ? array
|
||||
(
|
||||
'type' => 'select',
|
||||
'items' => $modules
|
||||
))
|
||||
) : 'input')
|
||||
),
|
||||
div
|
||||
(
|
||||
set::id('codeRow'),
|
||||
$codes
|
||||
? formGroup
|
||||
set::id('codesRow'),
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->block->lblBlock),
|
||||
set::name('code'),
|
||||
set::value($code),
|
||||
set::control(array
|
||||
set::class($showCodes ? '' : 'hidden'),
|
||||
set::value($showCodes ? $code : $module),
|
||||
set::control($showCodes ? array
|
||||
(
|
||||
'type' => 'select',
|
||||
'items' => array('') + $codes
|
||||
))
|
||||
) : null
|
||||
) : 'input')
|
||||
)
|
||||
),
|
||||
div
|
||||
(
|
||||
set::id('paramsRow'),
|
||||
set::class('form-grid'),
|
||||
$paramsRows,
|
||||
(($module and $code) or ($module and !$codes))
|
||||
? formGroup
|
||||
div
|
||||
(
|
||||
set::label($lang->block->name),
|
||||
set::name('title'),
|
||||
set::value(zget($modules, $module, '') . zget($codes, $code, '')),
|
||||
set::class('form-row'),
|
||||
set::control('input')
|
||||
) : null,
|
||||
(($module and $code) or ($module and !$codes))
|
||||
? formGroup
|
||||
(
|
||||
set::label($lang->block->grid),
|
||||
set::name("grid"),
|
||||
set::class('form-row'),
|
||||
set::control(array
|
||||
set::class('form-grid'),
|
||||
formGroup
|
||||
(
|
||||
'type' => 'select',
|
||||
'items' => $lang->block->gridOptions
|
||||
))
|
||||
) : null,
|
||||
set::label($lang->block->name),
|
||||
set::name('title'),
|
||||
set::class('form-row'),
|
||||
set::value(zget($modules, $module, '') . zget($codes, $code, '')),
|
||||
set::control('input')
|
||||
),
|
||||
$paramsRows,
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->block->grid),
|
||||
set::name("grid"),
|
||||
set::class('form-row'),
|
||||
set::control(array
|
||||
(
|
||||
'type' => 'select',
|
||||
'items' => $lang->block->gridOptions
|
||||
))
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -16,15 +16,14 @@ jsVar('blockID', $block->id);
|
||||
|
||||
$paramsRows = array();
|
||||
$showModules = ($dashboard == 'my' and $modules);
|
||||
$showCodes = ($module and $codes);
|
||||
$showParams = ($code);
|
||||
$showCodes = (($showModules and $module and $codes) or $dashboard != 'my');
|
||||
|
||||
foreach($params as $key => $row)
|
||||
{
|
||||
$paramsRows[] = formGroup
|
||||
(
|
||||
set::label($row['name']),
|
||||
set::name('params'),
|
||||
set::name("params[$key]"),
|
||||
set::class('form-row'),
|
||||
set::value($block->params->{$key}),
|
||||
set::control(array
|
||||
@@ -41,10 +40,10 @@ form
|
||||
on::change('#code', 'getForm'),
|
||||
formGroup
|
||||
(
|
||||
set::class($showModules ? '' : 'hidden'),
|
||||
set::value($showModules ? $block->module : $dashboard),
|
||||
set::label($lang->block->lblModule),
|
||||
set::name('module'),
|
||||
set::class($showModules ? '' : 'hidden'),
|
||||
set::value($showModules ? $module : $dashboard),
|
||||
set::control($showModules ? array
|
||||
(
|
||||
'type' => 'select',
|
||||
@@ -72,8 +71,7 @@ form
|
||||
set::id('paramsRow'),
|
||||
div
|
||||
(
|
||||
set::class('form-grid' . ($showParams ? '' : ' hidden')),
|
||||
$paramsRows,
|
||||
set::class('form-grid'),
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->block->name),
|
||||
@@ -82,6 +80,7 @@ form
|
||||
set::value($block->title),
|
||||
set::control('input')
|
||||
),
|
||||
$paramsRows,
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->block->grid),
|
||||
|
||||
+42
-7
@@ -71,7 +71,36 @@ class blockZen extends block
|
||||
if(!$this->block->checkAPI($this->get->hash)) return array();
|
||||
}
|
||||
|
||||
$blocks = $this->block->getAvailableBlocks($dashboard, $module);
|
||||
if($dashboard == 'my')
|
||||
{
|
||||
if($module and isset($this->lang->block->modules[$module]))
|
||||
{
|
||||
$blocks = $this->lang->block->modules[$module]->availableBlocks;
|
||||
}
|
||||
else
|
||||
{
|
||||
$blocks = array();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($dashboard and isset($this->lang->block->modules[$dashboard]))
|
||||
{
|
||||
$blocks = $this->lang->block->modules[$dashboard]->availableBlocks;
|
||||
}
|
||||
else
|
||||
{
|
||||
$blocks = $this->lang->block->availableBlocks;
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($this->config->block->closed))
|
||||
{
|
||||
foreach($blocks as $blockKey => $blockName)
|
||||
{
|
||||
if(strpos(",{$this->config->block->closed},", ",{$module}|{$blockKey},") !== false) unset($blocks[$blockKey]);
|
||||
}
|
||||
}
|
||||
|
||||
if(!$this->selfCall)
|
||||
{
|
||||
@@ -92,13 +121,19 @@ class blockZen extends block
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function getAvailableParams(string $dashboard, string $module = '', string $block = ''): array
|
||||
protected function getAvailableParams(string $dashboard, string $module = '', string $code = ''): array
|
||||
{
|
||||
if(!isset($this->lang->block->moduleList[$module])) return array();
|
||||
if($code == 'todo' || $code == 'list' || $module == 'assigntome')
|
||||
{
|
||||
$code = $module;
|
||||
}
|
||||
elseif($code == 'statistic')
|
||||
{
|
||||
$code = $module . $code;
|
||||
}
|
||||
|
||||
if(!$block) return array();
|
||||
|
||||
$params = json_decode($this->block->getParams($block, $module), true);
|
||||
$params = zget($this->config->block->params, $code, '');
|
||||
$params = json_decode(json_encode($params), true);
|
||||
|
||||
return !empty($params) ? $params : array();
|
||||
}
|
||||
@@ -144,7 +179,7 @@ class blockZen extends block
|
||||
* @param int $projectID
|
||||
* @return void
|
||||
*/
|
||||
private function getBlockMoreLink(object $block, int $project): void
|
||||
private function getBlockMoreLink(object $block, int $projectID): void
|
||||
{
|
||||
$code = $block->code;
|
||||
$source = empty($block->source) ? 'common' : $block->source;
|
||||
|
||||
+2
-12
@@ -337,19 +337,9 @@ class bugModel extends model
|
||||
|
||||
/* Get bugs by browse type. */
|
||||
$bugList = array();
|
||||
if($browseType == 'all')
|
||||
{
|
||||
$bugList = $this->bugTao->getAllBugs($productIdList, $projectID, $executionIdList, $branch, $modules, $orderBy, $pager);
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
|
||||
}
|
||||
elseif($browseType == 'review')
|
||||
{
|
||||
$bugList = $this->bugTao->getListByReviewToMe($productIdList, $projectID, $executionIdList, $branch, $modules, $orderBy, $pager);
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
|
||||
}
|
||||
if($browseType == 'bysearch') $bugList = $this->getBySearch($productIdList, $branch, $queryID, $orderBy, '', $pager, $projectID);
|
||||
elseif($browseType == 'needconfirm') $bugList = $this->bugTao->getListByNeedconfirm($productIdList, $projectID, $executionIdList, $branch, $modules, $orderBy, $pager);
|
||||
elseif($browseType == 'bysearch') $bugList = $this->getBySearch($productIdList, $branch, $queryID, $orderBy, '', $pager, $projectID);
|
||||
elseif(strpos(',bymodule,assigntome,openedbyme,resolvedbyme,assigntonull,unconfirmed,unresolved,unclosed,toclosed,longlifebugs,postponedbugs,overduebugs,assignedbyme,', ",$browseType,") !== false) $bugList = $this->bugTao->getListByBrowseType($browseType, $productIdList, $projectID, $executionIdList, $branch, $modules, $orderBy, $pager);
|
||||
elseif(strpos(',all,bymodule,assigntome,openedbyme,resolvedbyme,assigntonull,unconfirmed,unresolved,unclosed,toclosed,longlifebugs,postponedbugs,overduebugs,assignedbyme,review,', ",$browseType,") !== false) $bugList = $this->bugTao->getListByBrowseType($browseType, $productIdList, $projectID, $executionIdList, $branch, $modules, $orderBy, $pager);
|
||||
|
||||
return $this->bugTao->batchAppendDelayedDays($bugList);
|
||||
}
|
||||
|
||||
+2
-61
@@ -21,36 +21,6 @@ class bugTao extends bugModel
|
||||
->where('t1.id')->eq((int)$bugID)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all bugs.
|
||||
* 获取所有的bug。
|
||||
*
|
||||
* @param int|array $productIdList
|
||||
* @param int|string $branch
|
||||
* @param int|array $moduleIdList
|
||||
* @param int[] $executionIdList
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @param int $projectID
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function getAllBugs(int|array $productIdList, int $projectID, array $executionIdList, int|string $branch, int|array $moduleIdList, string $orderBy, object $pager = null): array
|
||||
{
|
||||
return $this->dao->select("t1.*, t2.title as planTitle, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1')
|
||||
->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id')
|
||||
->where('t1.deleted')->eq('0')
|
||||
->andWhere('t1.product')->in($productIdList)
|
||||
->beginIF($projectID)->andWhere('t1.project')->eq($projectID)->fi()
|
||||
->beginIF($this->app->tab !== 'qa')->andWhere('t1.execution')->in($executionIdList)->fi()
|
||||
->beginIF($branch !== 'all')->andWhere('t1.branch')->eq($branch)->fi()
|
||||
->beginIF($moduleIdList)->andWhere('t1.module')->in($moduleIdList)->fi()
|
||||
->beginIF(!$this->app->user->admin)->andWhere('t1.project')->in('0,' . $this->app->user->view->projects)->fi()
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bug list by browse type.
|
||||
* 通过浏览类型获取bug列表。
|
||||
@@ -100,6 +70,7 @@ class bugTao extends bugModel
|
||||
->beginIF($browseType == 'unresolved')->andWhere('status')->eq('active')->fi()
|
||||
->beginIF($browseType == 'toclosed')->andWhere('status')->eq('resolved')->fi()
|
||||
->beginIF($browseType == 'postponedbugs')->andWhere('resolution')->eq('postponed')->fi()
|
||||
->beginIF($browseType == 'review')->andWhere("FIND_IN_SET('{$this->app->user->account}', reviewers)")->fi()
|
||||
|
||||
->beginIF($browseType == 'longlifebugs')
|
||||
->andWhere('lastEditedDate')->lt($lastEditedDate)
|
||||
@@ -121,6 +92,7 @@ class bugTao extends bugModel
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug');
|
||||
return $bugList;
|
||||
}
|
||||
|
||||
@@ -156,37 +128,6 @@ class bugTao extends bugModel
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bug list to review.
|
||||
* 获取待我审批的bug列表。
|
||||
*
|
||||
* @param int|array $productIdList
|
||||
* @param int $projectID
|
||||
* @param int[] $executionIdList
|
||||
* @param int|string $branch
|
||||
* @param int|array $moduleIdList
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
protected function getListByReviewToMe(int|array $productIdList, int $projectID, array $executionIdList, int|string $branch, int|array $moduleIdList, string $orderBy, object $pager = null): array
|
||||
{
|
||||
return $this->dao->select("t1.*, t2.title as planTitle, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)->alias('t1')
|
||||
->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id')
|
||||
->where('t1.deleted')->eq(0)
|
||||
->andWhere('t1.product')->in($productIdList)
|
||||
->beginIF($projectID)->andWhere('t1.project')->eq($projectID)->fi()
|
||||
->beginIF($this->app->tab !== 'qa')->andWhere('t1.execution')->in($executionIdList)->fi()
|
||||
->beginIF($branch !== 'all')->andWhere('t1.branch')->eq($branch)->fi()
|
||||
->beginIF($moduleIdList)->andWhere('t1.module')->in($moduleIdList)->fi()
|
||||
->andWhere("FIND_IN_SET('{$this->app->user->account}', t1.reviewers)")
|
||||
->beginIF(!$this->app->user->admin)->andWhere('t1.project')->in('0,' . $this->app->user->view->projects)->fi()
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cases created by bug.
|
||||
* 获取bug建的用例。
|
||||
|
||||
@@ -64,7 +64,6 @@ r(count($bug->getList($browseType[0], $productIdList[2], $projectID[0], $execut
|
||||
r(count($bug->getList($browseType[0], $productIdList[0], $projectID[2], $executionIdList[0], $branch[0], $moduleID[0]))) && p('') && e('0'); //获取不存在项目ID的bug列表,查看数量是否正确
|
||||
r(count($bug->getList($browseType[0], $productIdList[0], $projectID[0], $executionIdList[2], $branch[0], $moduleID[0]))) && p('') && e('0'); //获取不存在执行ID的bug列表,查看数量是否正确
|
||||
|
||||
r($bug->getList($browseType[0], $productIdList[0], $projectID[0], $executionIdList[0], $branch[0], $moduleID[0])) && p('1:planTitle') && e('计划1'); //获取全部产品1下的全部bug列表,查看ID为1的bug的计划名称是否正确
|
||||
r($bug->getList($browseType[0], $productIdList[1], $projectID[1], $executionIdList[1], $branch[1], $moduleID[0])) && p('2:title') && e('BUG2'); //获取全部产品1下的项目相关的全部bug列表,查看ID为2的bug的名称是否正确
|
||||
r($bug->getList($browseType[1], $productIdList[0], $projectID[0], $executionIdList[0], $branch[0], $moduleID[1])) && p('3:module') && e('1'); //获取产品1模块下的bug列表,查看ID为3的bug的module是否正确
|
||||
r($bug->getList($browseType[2], $productIdList[0], $projectID[0], $executionIdList[0], $branch[0], $moduleID[0])) && p('1:assignedTo') && e('admin'); //获取产品1下指派给我的bug列表,查看ID为1的bug的指派人是否正确
|
||||
|
||||
@@ -77,7 +77,7 @@ class execution extends control
|
||||
$this->loadModel('product');
|
||||
|
||||
/* Get executions and products info. */
|
||||
$executionID = $this->execution->saveState($executionID, $this->executions);
|
||||
$executionID = $this->execution->checkAccess($executionID, $this->executions);
|
||||
$execution = $this->execution->getById($executionID);
|
||||
$products = $this->product->getProducts($executionID);
|
||||
$childExecutions = $this->execution->getChildExecutions($executionID);
|
||||
|
||||
@@ -322,8 +322,7 @@ class executionModel extends model
|
||||
}
|
||||
|
||||
/* Save session. */
|
||||
$this->session->set('execution', $executionID, $this->app->tab);
|
||||
$this->setProjectSession($executionID);
|
||||
$this->executionTao->saveSession($executionID);
|
||||
|
||||
/* Return execution id. */
|
||||
return $executionID;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The tao file of execution module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Shujie Tian <tianshujie@easysoft.ltd>
|
||||
* @package execution
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
class executionTao extends executionModel
|
||||
{
|
||||
/**
|
||||
* 将执行ID保存到session中。
|
||||
* Save the execution ID to the session.
|
||||
*
|
||||
* @param int $executionID
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function saveSession(int $executionID): void
|
||||
{
|
||||
$this->session->set('execution', $executionID, $this->app->tab);
|
||||
$this->setProjectSession($executionID);
|
||||
}
|
||||
}
|
||||
@@ -201,8 +201,12 @@ class product extends control
|
||||
if($browseType == 'bybranch') setcookie('storyBranch', $branch, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
|
||||
|
||||
$cookieModule = $this->app->tab == 'project' ? $this->cookie->storyModuleParam : $this->cookie->storyModule;
|
||||
$moduleID = ($browseType == 'bymodule') ? (int)$param : (($browseType == 'bysearch' or $browseType == 'bybranch') ? 0 : ($cookieModule ? $cookieModule : 0));
|
||||
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
|
||||
|
||||
$moduleID = 0;
|
||||
if($browseType == 'bymodule') $moduleID = (int)$param;
|
||||
elseif($browseType != 'bysearch' and $browseType != 'bybranch' and $cookieModule) $moduleID = $cookieModule;
|
||||
|
||||
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
|
||||
|
||||
/* Set moduleTree. */
|
||||
$createModuleLink = $storyType == 'story' ? 'createStoryLink' : 'createRequirementLink';
|
||||
@@ -1157,7 +1161,7 @@ class product extends control
|
||||
if($this->config->systemMode == 'light' and $orderBy == 'program_asc') $orderBy = 'order_asc';
|
||||
|
||||
$productStats = $this->product->getStats($orderBy, $pager, $browseType, 0, 'story', 0, $queryID);
|
||||
$productStructure = $this->product->statisticProgram($productStats);
|
||||
$productStructure = $this->productZen->statisticProgram($productStats);
|
||||
|
||||
/* Save search form. */
|
||||
$actionURL = $this->createLink('product', 'all', "browseType=bySearch&orderBy=order_asc&queryID=myQueryID");
|
||||
|
||||
+65
-166
@@ -1020,40 +1020,37 @@ class productModel extends model
|
||||
|
||||
/* Get modules. */
|
||||
$this->loadModel('tree');
|
||||
if($this->app->tab == 'project')
|
||||
if($this->app->tab == 'project' and $productID)
|
||||
{
|
||||
if($productID)
|
||||
$modules = array();
|
||||
$branchList = $this->loadModel('branch')->getPairs($productID, '', $projectID);
|
||||
$branchModuleList = $this->tree->getOptionMenu($productID, 'story', 0, array_keys($branchList));
|
||||
foreach($branchModuleList as $branchID => $branchModules) $modules = array_merge($modules, $branchModules);
|
||||
}
|
||||
elseif($this->app->tab == 'project')
|
||||
{
|
||||
$moduleList = array();
|
||||
$modules = array('/');
|
||||
$branchGroup = $this->loadModel('execution')->getBranchByProduct(array_keys($products), $projectID, '');
|
||||
foreach($products as $productID => $productName)
|
||||
{
|
||||
$modules = array();
|
||||
$branchList = $this->loadModel('branch')->getPairs($productID, '', $projectID);
|
||||
$branchModuleList = $this->tree->getOptionMenu($productID, 'story', 0, array_keys($branchList));
|
||||
foreach($branchModuleList as $branchID => $branchModules) $modules = array_merge($modules, $branchModules);
|
||||
}
|
||||
else
|
||||
{
|
||||
$moduleList = array();
|
||||
$modules = array('/');
|
||||
$branchGroup = $this->loadModel('execution')->getBranchByProduct(array_keys($products), $projectID, '');
|
||||
foreach($products as $productID => $productName)
|
||||
if(isset($branchGroup[$productID]))
|
||||
{
|
||||
if(isset($branchGroup[$productID]))
|
||||
$branchModuleList = $this->tree->getOptionMenu($productID, 'story', 0, array_keys($branchGroup[$productID]));
|
||||
foreach($branchModuleList as $branchID => $branchModules)
|
||||
{
|
||||
$branchModuleList = $this->tree->getOptionMenu($productID, 'story', 0, array_keys($branchGroup[$productID]));
|
||||
foreach($branchModuleList as $branchID => $branchModules)
|
||||
{
|
||||
if(is_array($branchModules)) $moduleList += $branchModules;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$moduleList = $this->tree->getOptionMenu($productID, 'story', 0, $branch);
|
||||
if(is_array($branchModules)) $moduleList += $branchModules;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$moduleList = $this->tree->getOptionMenu($productID, 'story', 0, $branch);
|
||||
}
|
||||
|
||||
foreach($moduleList as $moduleID => $moduleName)
|
||||
{
|
||||
if(empty($moduleID)) continue;
|
||||
$modules[$moduleID] = $productName . $moduleName;
|
||||
}
|
||||
foreach($moduleList as $moduleID => $moduleName)
|
||||
{
|
||||
if(empty($moduleID)) continue;
|
||||
$modules[$moduleID] = $productName . $moduleName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1686,19 +1683,19 @@ class productModel extends model
|
||||
if(empty($products)) return array();
|
||||
|
||||
/* Get stats data. */
|
||||
$productKeys = array_keys($products);
|
||||
$products = $this->productTao->getStatsProducts($productKeys,$programID, $orderBy, $pager);
|
||||
$productIDs = array_keys($products);
|
||||
$products = $this->productTao->getStatsProducts($productIDs,$programID, $orderBy, $pager);
|
||||
$finishClosedStory = $this->productTao->getFinishClosedStoryTODO();
|
||||
$unclosedStory = $this->productTao->getUnClosedStoryTODO();
|
||||
$plans = $this->productTao->getPlansTODO($productKeys);
|
||||
$releases = $this->productTao->getReleasesTODO($productKeys);
|
||||
$bugs = $this->productTao->getBugsTODO($productKeys);
|
||||
$unResolved = $this->productTao->getUnResolvedTODO($productKeys);
|
||||
$fixedBugs = $this->productTao->getFixedBugsTODO($productKeys);
|
||||
$closedBugs = $this->productTao->getClosedBugsTODO($productKeys);
|
||||
$thisWeekBugs = $this->productTao->getThisWeekBugsTODO($productKeys);
|
||||
$assignToNull = $this->productTao->getAssignToNullTODO($productKeys);
|
||||
list($stories, $reqs) = $this->productTao->getStatsStoriesAndRequirements($productKeys, $storyType);
|
||||
$plans = $this->productTao->getPlansTODO($productIDs);
|
||||
$releases = $this->productTao->getReleasesTODO($productIDs);
|
||||
$bugs = $this->productTao->getBugsTODO($productIDs);
|
||||
$unResolved = $this->productTao->getUnResolvedTODO($productIDs);
|
||||
$fixedBugs = $this->productTao->getFixedBugsTODO($productIDs);
|
||||
$closedBugs = $this->productTao->getClosedBugsTODO($productIDs);
|
||||
$thisWeekBugs = $this->productTao->getThisWeekBugsTODO($productIDs);
|
||||
$assignToNull = $this->productTao->getAssignToNullTODO($productIDs);
|
||||
list($stories, $reqs) = $this->productTao->getStatsStoriesAndRequirements($productIDs, $storyType);
|
||||
|
||||
/* Render statistic result to each product. */
|
||||
$stats = array();
|
||||
@@ -1863,39 +1860,35 @@ class productModel extends model
|
||||
|
||||
$rateCount = 0;
|
||||
$allCount = 0;
|
||||
foreach($stories as $key => $story)
|
||||
foreach($stories as $story)
|
||||
{
|
||||
if(!empty($story->type) && $story->type != $storyType) continue;
|
||||
|
||||
$totalEstimate += $story->estimate;
|
||||
$allCount ++;
|
||||
|
||||
/* When the status is not closed or closedReason is done or postponed then add cases rate..*/
|
||||
if(
|
||||
empty($story->children) and
|
||||
($story->status != 'closed' or
|
||||
($story->status == 'closed' and ($story->closedReason == 'done' or $story->closedReason == 'postponed')))
|
||||
)
|
||||
if(empty($story->children))
|
||||
{
|
||||
$storyIdList[] = $story->id;
|
||||
$rateCount ++;
|
||||
if($story->status != 'closed' or ($story->status == 'closed' and in_array($story->closedReason, ['done', 'postponed'])))
|
||||
{
|
||||
$storyIdList[] = $story->id;
|
||||
$rateCount ++;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$allCount ++;
|
||||
if(!empty($story->children))
|
||||
foreach($story->children as $child)
|
||||
{
|
||||
foreach($story->children as $child)
|
||||
{
|
||||
if($child->type != $storyType) continue;
|
||||
if($child->type != $storyType) continue;
|
||||
|
||||
if(
|
||||
$child->status != 'closed' or
|
||||
($child->status == 'closed' and ($child->closedReason == 'done' or $child->closedReason == 'postponed'))
|
||||
)
|
||||
{
|
||||
$storyIdList[] = $child->id;
|
||||
$rateCount ++;
|
||||
}
|
||||
$allCount ++;
|
||||
if($story->status != 'closed' or ($story->status == 'closed' and in_array($story->closedReason, ['done', 'postponed'])))
|
||||
{
|
||||
$storyIdList[] = $child->id;
|
||||
$rateCount ++;
|
||||
}
|
||||
$allCount ++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1909,103 +1902,6 @@ class productModel extends model
|
||||
return sprintf($this->lang->product->storySummary, $allCount, $storyCommon, $totalEstimate, $rate * 100 . "%");
|
||||
}
|
||||
|
||||
/**
|
||||
* Statistics program data from statistics data of product.
|
||||
*
|
||||
* @param array $productStats
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function statisticProgram(array $productStats): array
|
||||
{
|
||||
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getProductStats();
|
||||
|
||||
$productStructure = array();
|
||||
|
||||
foreach($productStats as $product)
|
||||
{
|
||||
$productStructure[$product->program][$product->line]['products'][$product->id] = $product;
|
||||
if($product->line)
|
||||
{
|
||||
/* Line name. */
|
||||
$productStructure[$product->program][$product->line]['lineName'] = $product->lineName;
|
||||
$productStructure[$product->program][$product->line] = $this->statisticData('line', $productStructure, $product);
|
||||
}
|
||||
|
||||
if($product->program)
|
||||
{
|
||||
/* Init vars. */
|
||||
/* Program name. */
|
||||
$productStructure[$product->program]['programName'] = $product->programName;
|
||||
$productStructure[$product->program]['programPM'] = $product->programPM;
|
||||
$productStructure[$product->program]['id'] = $product->program;
|
||||
$productStructure[$product->program] = $this->statisticData('program', $productStructure, $product);
|
||||
}
|
||||
}
|
||||
|
||||
return $productStructure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Statistic product data.
|
||||
*
|
||||
* @param string $type
|
||||
* @param array $productStructure
|
||||
* @param object $product
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function statisticData($type = 'program', $productStructure = array(), $product = null)
|
||||
{
|
||||
if(empty($productStructure)) return $productStructure;
|
||||
|
||||
/* Init vars. */
|
||||
$data = $type == 'program' ? $productStructure[$product->program] : $productStructure[$product->program][$product->line];
|
||||
foreach($this->config->product->statisticFields as $key => $fields)
|
||||
{
|
||||
/* Get the total number of requirements and stories. */
|
||||
if(strpos('stories|requirements', $key) !== false)
|
||||
{
|
||||
$totalObjects = 0;
|
||||
foreach($product->$key as $status => $number)
|
||||
{
|
||||
if(isset($this->lang->story->statusList[$status])) $totalObjects += $number;
|
||||
}
|
||||
|
||||
$fieldType = $key == 'stories' ? 'Stories' : 'Requirements';
|
||||
if(!isset($data['total' . $fieldType])) $data['total' . $fieldType] = 0;
|
||||
$data['total' . $fieldType] += $totalObjects;
|
||||
}
|
||||
elseif($key == 'bugs')
|
||||
{
|
||||
$fieldType = 'Bugs';
|
||||
}
|
||||
|
||||
foreach($fields as $field)
|
||||
{
|
||||
if(!isset($data[$field])) $data[$field] = 0;
|
||||
|
||||
$status = $field;
|
||||
if(strpos($field, 'Requirements') !== false or strpos($field, 'Stories') !== false or $field == 'unResolvedBugs')
|
||||
{
|
||||
$length = strpos($field, $fieldType);
|
||||
$status = substr($field, 0, $length);
|
||||
}
|
||||
|
||||
if(strpos('requirements|stories', $key) !== false)
|
||||
{
|
||||
$objects = $product->$key;
|
||||
$data[$field] += $objects[$status];
|
||||
}
|
||||
else
|
||||
{
|
||||
$data[$field] += $product->$status;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Judge an action is clickable or not.
|
||||
*
|
||||
@@ -2300,18 +2196,21 @@ class productModel extends model
|
||||
*
|
||||
* Set menu.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int|string $branch
|
||||
* @param int $module
|
||||
* @param string $moduleType
|
||||
* @param string $extra
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int|string $branch
|
||||
* @param int $module
|
||||
* @param string $moduleType
|
||||
* @param string $extra
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setMenu($productID = 0, $branch = '', $module = 0, $moduleType = '', $extra = '')
|
||||
public function setMenu($productID = 0, $branch = '', $module = 0, $moduleType = '', $extra = ''): void
|
||||
{
|
||||
if(!$this->app->user->admin and strpos(",{$this->app->user->view->products},", ",$productID,") === false and $productID != 0 and !defined('TUTORIAL')) return $this->accessDenied($this->lang->product->accessDenied);
|
||||
if(!$this->app->user->admin and strpos(",{$this->app->user->view->products},", ",$productID,") === false and $productID != 0 and !defined('TUTORIAL'))
|
||||
{
|
||||
$this->accessDenied($this->lang->product->accessDenied);
|
||||
return;
|
||||
}
|
||||
|
||||
$product = $this->getByID($productID);
|
||||
|
||||
|
||||
+13
-1
@@ -97,7 +97,6 @@ class productTao extends productModel
|
||||
*/
|
||||
protected function getPagerProductsIn(array $productIDs, object|null $pager, string $orderBy)
|
||||
{
|
||||
/* TODO list all fields? */
|
||||
$products = $this->dao->select('*')->from(TABLE_PRODUCT)
|
||||
->where('id')->in($productIDs)
|
||||
->orderBy($orderBy)
|
||||
@@ -494,4 +493,17 @@ class productTao extends productModel
|
||||
if(dao::isError())return false;
|
||||
return (int)$this->dao->lastInsertID();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从module表中查询所有产品线。
|
||||
* Get all product lines from module table.
|
||||
* TODO move to the MODULE module.
|
||||
*
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function getProductLinesTODO(): array
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('line')->andWhere('deleted')->eq(0)->orderBy('`order` asc')->fetchAll();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
include dirname(__FILE__, 2) . '/product.class.php';
|
||||
|
||||
function initData()
|
||||
{
|
||||
/* Generate product data. */
|
||||
$product = zdTable('product')->config('getlist');
|
||||
$product->name->prefix('产品_')->range('1-50');
|
||||
$product->code->prefix('p_code_')->range('1-50');
|
||||
$product->order->range('1-50');
|
||||
$product->status->range('noclosed,involved,review,normal,closed');
|
||||
$product->vision->range('rnd,lite,');
|
||||
$product->gen(50);
|
||||
|
||||
/* Generate releated program data. */
|
||||
$program = zdTable('project');
|
||||
$program->id->range('1-10');
|
||||
$program->model->range('');
|
||||
$program->name->prefix('项目集_')->range('1-10');
|
||||
$program->type->range('program,project');
|
||||
$program->project->range('0');
|
||||
$program->vision->range('rnd');
|
||||
$program->gen(10);
|
||||
|
||||
/* Generate releate product to project data. */
|
||||
$project2product = zdTable('projectproduct');
|
||||
$project2product->project->range('2,4,6,8,10');
|
||||
$project2product->product->range('1-50');
|
||||
$project2product->branch->range('0');
|
||||
$project2product->plan->range('0');
|
||||
$project2product->gen(50);
|
||||
|
||||
/* Generate releated team data. */
|
||||
$team = zdTable('team');
|
||||
$team->type->range('project');
|
||||
$team->root->range('2,4,6,8,10');
|
||||
$team->gen(5);
|
||||
|
||||
}
|
||||
initData();
|
||||
|
||||
/**
|
||||
|
||||
title=productTao->getList();
|
||||
cid=2
|
||||
|
||||
- 校验总数 @25
|
||||
- 校验shadow总数 @25
|
||||
- 校验line总数 @5
|
||||
- 校验limit @3
|
||||
- 校验noclosed状态 @20
|
||||
- 校验所属项目集 @5
|
||||
|
||||
*/
|
||||
|
||||
global $config;
|
||||
|
||||
$product = new productTest('admin');
|
||||
|
||||
/* Valiate defualt total. */
|
||||
$result = $product->objectModel->getList(0, 'all', 0, 0, 'all');
|
||||
r(count($result)) && p('') && e('25');
|
||||
|
||||
/* Validate shadow total. */
|
||||
$result = $product->objectModel->getList(0, 'all', 0, 0, 0);
|
||||
r(count($result)) && p('') && e('25');
|
||||
|
||||
/* Validate line total. */
|
||||
$result = $product->objectModel->getList(0, 'all', 0, 1, 0);
|
||||
r(count($result)) && p('') && e('5');
|
||||
|
||||
/* Validate limit. */
|
||||
$result = $product->objectModel->getList(0, 'all', 3, 1, 0);
|
||||
r(count($result)) && p('') && e('3');
|
||||
|
||||
/* Validate noclosed status. */
|
||||
$result = $product->objectModel->getList(0, 'noclosed', 0, 0, 0);
|
||||
r(count($result)) && p('') && e('20');
|
||||
|
||||
/* Validate noclosed status. */
|
||||
$result = $product->objectModel->getList(1, 'noclosed', 0, 0, 0);
|
||||
r(count($result)) && p('') && e('5');
|
||||
@@ -0,0 +1,12 @@
|
||||
title: table zt_product for getList testing
|
||||
author: Chen Tao
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-50
|
||||
- field: program
|
||||
range: 1-10
|
||||
- field: shadow
|
||||
range: 0-1
|
||||
- field: line
|
||||
range: 1-5
|
||||
@@ -1,13 +1,178 @@
|
||||
<?php
|
||||
js::set('programID', $programID);
|
||||
/**
|
||||
* The create view of product of ZenTaoPMS.
|
||||
*/
|
||||
|
||||
$form = form();
|
||||
$form->buildForm($fields);
|
||||
$form->buildFormAction();
|
||||
/*
|
||||
======= Attention ======
|
||||
|
||||
$content = block();
|
||||
$content->from = $form;
|
||||
This file is generated by zin-tool, you should check the following to-do list.
|
||||
|
||||
$page = page('create');
|
||||
$page->right->content = $content;
|
||||
$page->x();
|
||||
+ Familiar with the use of these widgets in zin: .
|
||||
+ Check the following variables which used in widgets: $programOptions, $lineOptions, $POOptions, $QDOptions, $RDOptions, $reviewerOptions, $typeOptions, $aclOptions, $whitelistOptions.
|
||||
+ Check the origin code in module/product/view/create.html.php, and ensure that all features have been implemented.
|
||||
+ Check the origin js code in module/product/js/common.js and module/product/js/create.js
|
||||
+ Check the origin css code in module/product/css/common.css and module/product/css/create.css
|
||||
+ Remove the comments which starts with "zin:"
|
||||
+ Test according to the new design draft and the original implementation
|
||||
*/
|
||||
|
||||
namespace zin;
|
||||
|
||||
/* ====== Preparing and processing page data ====== */
|
||||
|
||||
/* zin: Set variables to define picker options for form */
|
||||
$programOptions = array();
|
||||
$lineOptions = array();
|
||||
$POOptions = array();
|
||||
$QDOptions = array();
|
||||
$RDOptions = array();
|
||||
$reviewerOptions = array();
|
||||
$typeOptions = array(array('value' => "normal", 'text' => "正常"), array('value' => "branch", 'text' => "多分支(适用于客户定制场景)"), array('value' => "platform", 'text' => "多平台(适用于跨平台应用开发,比如IOS、安卓、PC端等)"));
|
||||
$aclOptions = array(array('checked' => true, 'value' => "private", 'disabled' => false, 'text' => "私有(产品相关负责人、所属项目集的负责人及干系人、相关联项目的团队成员和干系人可访问)"), array('checked' => false, 'value' => "open", 'disabled' => false, 'text' => "公开(有产品视图权限,即可访问)"));
|
||||
$whitelistOptions = array();
|
||||
|
||||
|
||||
/* ====== Define the page structure with zin widgets ====== */
|
||||
|
||||
/* zin: Define the form in main content */
|
||||
formPanel
|
||||
(
|
||||
formGroup
|
||||
(
|
||||
set::width("1/3"),
|
||||
set::name("program"),
|
||||
set::label("项目集"),
|
||||
set::control("picker"),
|
||||
set::items($programOptions)
|
||||
),
|
||||
formRow
|
||||
(
|
||||
set::hidden(true),
|
||||
formGroup
|
||||
(
|
||||
set::width("1/3"),
|
||||
set::name("line"),
|
||||
set::label("产品线"),
|
||||
set::control("picker"),
|
||||
set::items($lineOptions)
|
||||
)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::width("1/3"),
|
||||
set::name("name"),
|
||||
set::label("产品名称"),
|
||||
set::required(true),
|
||||
set::control("text")
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::width("1/3"),
|
||||
set::name("PO"),
|
||||
set::label("产品负责人"),
|
||||
set::control("picker"),
|
||||
set::items($POOptions)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::width("1/3"),
|
||||
set::name("QD"),
|
||||
set::label("测试负责人"),
|
||||
set::control("picker"),
|
||||
set::items($QDOptions)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::width("1/3"),
|
||||
set::name("RD"),
|
||||
set::label("发布负责人"),
|
||||
set::control("picker"),
|
||||
set::items($RDOptions)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::width("1/3"),
|
||||
set::name("reviewer[]"),
|
||||
set::label("评审人"),
|
||||
set::control(["type" =>"picker","multiple"=>true]),
|
||||
set::id("reviewer"),
|
||||
set::items($reviewerOptions)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::width("1/3"),
|
||||
set::name("type"),
|
||||
set::label("产品类型"),
|
||||
set::value("normal"),
|
||||
set::control("picker"),
|
||||
set::items($typeOptions)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::width("2/3"),
|
||||
set::label("产品描述"),
|
||||
inputGroup
|
||||
(
|
||||
control(set(array
|
||||
(
|
||||
'id' => "title",
|
||||
'value' => "",
|
||||
'disabled' => false,
|
||||
'type' => "text"
|
||||
))),
|
||||
"公共",
|
||||
btn(set(array
|
||||
(
|
||||
'type' => "btn",
|
||||
'text' => "保存",
|
||||
'class' => "input-group-btn"
|
||||
)))
|
||||
)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::width("2/3"),
|
||||
set::name("acl"),
|
||||
set::label("访问控制"),
|
||||
set::control("radioList"),
|
||||
set::items($aclOptions)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::width("1/3"),
|
||||
set::label("白名单"),
|
||||
inputGroup
|
||||
(
|
||||
control(set(array
|
||||
(
|
||||
'name' => "whitelist[]",
|
||||
'id' => "whitelist",
|
||||
'value' => NULL,
|
||||
'disabled' => false,
|
||||
'type' => "picker",
|
||||
'items' => $whitelistOptions,
|
||||
'multiple' => true
|
||||
))),
|
||||
btn(set(array
|
||||
(
|
||||
'type' => "btn",
|
||||
'icon' => "cog",
|
||||
'text' => "",
|
||||
'class' => "input-group-btn"
|
||||
))),
|
||||
btn(set(array
|
||||
(
|
||||
'type' => "btn",
|
||||
'icon' => "refresh",
|
||||
'text' => "",
|
||||
'class' => "input-group-btn"
|
||||
)))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
/* ====== Render page ====== */
|
||||
|
||||
render();
|
||||
|
||||
+98
-2
@@ -247,8 +247,7 @@ class productZen extends product
|
||||
protected function getProductLines(): array
|
||||
{
|
||||
/* Get all product lines. */
|
||||
/* TODO use model of module. */
|
||||
$productLines = $this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('line')->andWhere('deleted')->eq(0)->orderBy('`order` asc')->fetchAll();
|
||||
$productLines = $this->product->getProductLinesTODO();
|
||||
|
||||
/* Collect product lines of program lines. */
|
||||
$programLines = array();
|
||||
@@ -457,4 +456,101 @@ class productZen extends product
|
||||
{
|
||||
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从产品统计数据中统计项目集。
|
||||
* Statistics program data from statistics data of product.
|
||||
*
|
||||
* @param array $productStats
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function statisticProgram(array $productStats): array
|
||||
{
|
||||
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getProductStats();
|
||||
|
||||
$programStructure = array();
|
||||
|
||||
foreach($productStats as $product)
|
||||
{
|
||||
$programStructure[$product->program][$product->line]['products'][$product->id] = $product;
|
||||
|
||||
/* Generate line data. */
|
||||
if($product->line)
|
||||
{
|
||||
$programStructure[$product->program][$product->line]['lineName'] = $product->lineName;
|
||||
$programStructure[$product->program][$product->line] = $this->statisticProductData('line', $programStructure, $product);
|
||||
}
|
||||
|
||||
/* Generate program data. */
|
||||
if($product->program)
|
||||
{
|
||||
$programStructure[$product->program]['programName'] = $product->programName;
|
||||
$programStructure[$product->program]['programPM'] = $product->programPM;
|
||||
$programStructure[$product->program]['id'] = $product->program;
|
||||
$programStructure[$product->program] = $this->statisticProductData('program', $programStructure, $product);
|
||||
}
|
||||
}
|
||||
|
||||
return $programStructure;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计项目集内的产品数据
|
||||
* Statistic product data.
|
||||
*
|
||||
* @param string $type line|program
|
||||
* @param array $programStructure
|
||||
* @param object $product
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function statisticProductData(string $type, array $programStructure, object|null $product): array
|
||||
{
|
||||
if(empty($programStructure)) return $programStructure;
|
||||
|
||||
/* Init vars. */
|
||||
$data = $type == 'program' ? $programStructure[$product->program] : $programStructure[$product->program][$product->line];
|
||||
foreach($this->config->product->statisticFields as $key => $fields)
|
||||
{
|
||||
/* Get the total number of requirements and stories. */
|
||||
if(strpos('stories|requirements', $key) !== false)
|
||||
{
|
||||
$totalObjects = 0;
|
||||
foreach($product->$key as $status => $number) if(isset($this->lang->story->statusList[$status])) $totalObjects += $number;
|
||||
|
||||
$fieldType = $key == 'stories' ? 'Stories' : 'Requirements';
|
||||
if(!isset($data['total' . $fieldType])) $data['total' . $fieldType] = 0;
|
||||
$data['total' . $fieldType] += $totalObjects;
|
||||
}
|
||||
elseif($key == 'bugs')
|
||||
{
|
||||
$fieldType = 'Bugs';
|
||||
}
|
||||
|
||||
foreach($fields as $field)
|
||||
{
|
||||
if(!isset($data[$field])) $data[$field] = 0;
|
||||
|
||||
$status = $field;
|
||||
if(strpos($field, 'Requirements') !== false or strpos($field, 'Stories') !== false or $field == 'unResolvedBugs')
|
||||
{
|
||||
$length = strpos($field, $fieldType);
|
||||
$status = substr($field, 0, $length);
|
||||
}
|
||||
|
||||
if(strpos('requirements|stories', $key) !== false)
|
||||
{
|
||||
$objects = $product->$key;
|
||||
$data[$field] += $objects[$status];
|
||||
}
|
||||
else
|
||||
{
|
||||
$data[$field] += $product->$status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<?php
|
||||
$config->project->form = new stdclass();
|
||||
|
||||
$config->project->form->create = array();
|
||||
$config->project->form->edit = array();
|
||||
$config->project->form->close = array();
|
||||
$config->project->form->start = array();
|
||||
|
||||
$config->project->form->create['parent'] = array('type' => 'int', 'required' => false, 'default' => '');
|
||||
$config->project->form->create['name'] = array('type' => 'string', 'required' => true, 'filter' => 'trim');
|
||||
$config->project->form->create['code'] = array('type' => 'string', 'required' => true, 'filter' => 'trim');
|
||||
@@ -17,7 +22,6 @@ $config->project->form->create['whitelist'] = array('type' => 'array', 'requir
|
||||
$config->project->form->create['auth'] = array('type' => 'array', 'required' => false, 'default' => '');
|
||||
$config->project->form->create['model'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
|
||||
$config->project->form->eidt = array();
|
||||
$config->project->form->edit['parent'] = array('type' => 'int', 'required' => false, 'default' => '');
|
||||
$config->project->form->edit['name'] = array('type' => 'string', 'required' => true, 'filter' => 'trim');
|
||||
$config->project->form->edit['code'] = array('type' => 'string', 'required' => true, 'filter' => 'trim');
|
||||
@@ -33,6 +37,7 @@ $config->project->form->edit['acl'] = array('type' => 'string', 'required
|
||||
$config->project->form->edit['whitelist'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join');
|
||||
$config->project->form->edit['auth'] = array('type' => 'array', 'required' => false, 'default' => '');
|
||||
$config->project->form->edit['model'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
|
||||
$config->project->form->start['realBegan'] = array('type' => 'date', 'required' => true, 'filter' => 'trim');
|
||||
|
||||
$config->project->form->close['realEnd'] = array('type' => 'date', 'required' => true, 'filter' => 'trim');
|
||||
|
||||
+32
-158
@@ -511,7 +511,7 @@ class project extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function edit(string $projectID, string $from = ''): void
|
||||
public function edit(string $projectID, string $from = ''): mixed
|
||||
{
|
||||
$this->loadModel('action');
|
||||
$this->loadModel('custom');
|
||||
@@ -1674,12 +1674,14 @@ class project extends control
|
||||
/**
|
||||
* Project edit a group.
|
||||
*
|
||||
* @param int $groupID
|
||||
* @param string $groupID
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function editGroup($groupID)
|
||||
public function editGroup($groupID): mixed
|
||||
{
|
||||
$groupID = (int)$groupID;
|
||||
$this->loadModel('group');
|
||||
if(!empty($_POST))
|
||||
{
|
||||
@@ -1687,10 +1689,8 @@ class project extends control
|
||||
return print(js::closeModal('parent.parent', 'this'));
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->edit;
|
||||
$this->view->position[] = $this->lang->group->edit;
|
||||
$this->view->group = $this->group->getById($groupID);
|
||||
|
||||
$this->view->title = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->edit;
|
||||
$this->view->group = $this->group->getById($groupID);
|
||||
$this->display('group', 'edit');
|
||||
}
|
||||
|
||||
@@ -1804,8 +1804,7 @@ class project extends control
|
||||
$changes = $this->project->activate($projectID, $postData);
|
||||
if(dao::isError()) return print(js::error(dao::getError()));
|
||||
|
||||
$comment = strip_tags($this->post->comment, $this->config->allowedTags);
|
||||
$this->projectZen->responseAfterActivate($projectID, $changes, $comment);
|
||||
$this->projectZen->responseAfterActivate($projectID, $changes);
|
||||
return print(js::reload('parent.parent'));
|
||||
}
|
||||
|
||||
@@ -1935,79 +1934,34 @@ class project extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理项目下的关联产品
|
||||
* Manage products.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $projectID
|
||||
* @param string $from project|program|programproject
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function manageProducts(string $projectID, $from = 'project')
|
||||
public function manageProducts(string $projectID, $from = 'project'): mixed
|
||||
{
|
||||
$projectID = (int)$projectID;
|
||||
|
||||
$this->loadModel('product');
|
||||
$this->loadModel('program');
|
||||
$this->loadModel('execution');
|
||||
|
||||
$project = $this->project->getById($projectID);
|
||||
$project = $this->project->getById($projectID);
|
||||
if(!$project->hasProduct) return print(js::error($this->lang->project->cannotManageProducts) . js::locate('back'));
|
||||
|
||||
$executions = $this->execution->getPairs($projectID);
|
||||
$executions = $this->loadModel('execution')->getPairs($projectID);
|
||||
$executionIDs = array_keys($executions);
|
||||
|
||||
if(!empty($_POST))
|
||||
{
|
||||
if(!isset($_POST['products']) and !isset($_POST['otherProducts']))
|
||||
$postData = form::data();
|
||||
if(!isset($postData->rawdata->products) and !isset($postData->rawdata->otherProducts))
|
||||
{
|
||||
dao::$errors['message'][] = $this->lang->project->errorNoProducts;
|
||||
return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
}
|
||||
|
||||
$oldProducts = $this->product->getProducts($projectID);
|
||||
if($project->multiple and $project->model != 'waterfall' and $project->model != 'waterfallplus') $oldExecutionProducts = $this->dao->select('project,product')->from(TABLE_PROJECTPRODUCT)->where('project')->in(array_keys($executions))->fetchGroup('project', 'product');
|
||||
|
||||
$this->project->updateProducts($projectID);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
if(empty($project->multiple))
|
||||
{
|
||||
$executionID = $this->execution->getNoMultipleID($projectID);
|
||||
if($executionID) $this->execution->updateProducts($executionID);
|
||||
}
|
||||
|
||||
$newProducts = $this->product->getProducts($projectID);
|
||||
$oldProductIDs = array_keys($oldProducts);
|
||||
$newProductIDs = array_keys($newProducts);
|
||||
$diffProducts = array_merge(array_diff($oldProductIDs, $newProductIDs), array_diff($newProductIDs, $oldProductIDs));
|
||||
if($diffProducts) $this->loadModel('action')->create('project', $projectID, 'Managed', '', !empty($_POST['products']) ? join(',', $_POST['products']) : '');
|
||||
|
||||
if(empty($project->division))
|
||||
{
|
||||
foreach(array_keys($executions) as $executionID)
|
||||
{
|
||||
$this->execution->updateProducts($executionID);
|
||||
if($diffProducts) $this->loadModel('action')->create('execution', $executionID, 'Managed', '', implode(',', array_keys($newProducts)));
|
||||
}
|
||||
}
|
||||
|
||||
if($project->multiple and $project->model != 'waterfall' and $project->model != 'waterfallplus')
|
||||
{
|
||||
$unlinkedProducts = array_diff($oldProductIDs, $newProductIDs);
|
||||
if(!empty($unlinkedProducts))
|
||||
{
|
||||
$unlinkedProductPairs = array();
|
||||
foreach($unlinkedProducts as $unlinkedProduct) $unlinkedProductPairs[$unlinkedProduct] = $oldProducts[$unlinkedProduct]->name;
|
||||
|
||||
$unlinkExecutions = array();
|
||||
foreach($oldExecutionProducts as $executionID => $executionProducts)
|
||||
{
|
||||
$unlinkExecutionProducts = array_intersect_key($unlinkedProductPairs, $executionProducts);
|
||||
if($unlinkExecutionProducts) $unlinkExecutions[$executionID] = $unlinkExecutionProducts;
|
||||
}
|
||||
|
||||
foreach($unlinkExecutions as $executionID => $unlinkExecutionProducts) $this->action->create('execution', $executionID, 'unlinkproduct', '', implode(',', $unlinkExecutionProducts));
|
||||
}
|
||||
}
|
||||
$this->projectZen->mergeProducts($projectID, $project, $executionIDs, $postData);
|
||||
|
||||
$locateLink = inLink('manageProducts', "projectID=$projectID");
|
||||
if($from == 'program') $locateLink = $this->session->projectList;
|
||||
@@ -2023,125 +1977,45 @@ class project extends control
|
||||
$this->project->setMenu($projectID);
|
||||
}
|
||||
|
||||
$linkedBranches = array();
|
||||
$linkedBranchIdList = array();
|
||||
$branches = $this->project->getBranchesByProject($projectID);
|
||||
$linkedProductIdList = empty($branches) ? '' : array_keys($branches);
|
||||
$allProducts = $this->program->getProductPairs($project->parent, 'all', 'noclosed', $linkedProductIdList);
|
||||
$linkedProducts = $this->product->getProducts($projectID, 'all', '', true, $linkedProductIdList);
|
||||
$projectStories = $this->project->getStoriesByProject($projectID);
|
||||
$projectBranches = $this->project->getBranchGroupByProject($projectID, array_keys($linkedProducts));
|
||||
|
||||
/* If the story of the product which linked the project, you don't allow to remove the product. */
|
||||
$unmodifiableProducts = array();
|
||||
$unmodifiableBranches = array();
|
||||
$unmodifiableMainBranches = array();
|
||||
foreach($linkedProducts as $productID => $linkedProduct)
|
||||
{
|
||||
$linkedBranches[$productID] = array();
|
||||
foreach($branches[$productID] as $branchID => $branch)
|
||||
{
|
||||
$linkedBranches[$productID][$branchID] = $branchID;
|
||||
$linkedBranchIdList[$branchID] = $branchID;
|
||||
|
||||
if(!empty($projectStories[$productID][$branchID]) or !empty($projectBranches[$productID][$branchID]))
|
||||
{
|
||||
if($branchID == BRANCH_MAIN) $unmodifiableMainBranches[$productID] = $branchID;
|
||||
array_push($unmodifiableProducts, $productID);
|
||||
array_push($unmodifiableBranches, $branchID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$branchGroups = $this->loadModel('branch')->getByProducts(array_keys($allProducts), 'ignoreNormal|noclosed', $linkedBranchIdList);
|
||||
if($this->config->systemMode == 'ALM')
|
||||
{
|
||||
$topProgramID = $project->parent ? $this->program->getTopByPath($project->path) : 0;
|
||||
$productsGroupByProgram = $this->product->getProductsGroupByProgram();
|
||||
|
||||
$currentProducts = array();
|
||||
$otherProducts = array();
|
||||
foreach($productsGroupByProgram as $programID => $programProducts)
|
||||
{
|
||||
if($programID != $topProgramID)
|
||||
{
|
||||
foreach($programProducts as $productID => $productName)
|
||||
{
|
||||
if(!empty($branchGroups[$productID]))
|
||||
{
|
||||
foreach($branchGroups[$productID] as $branchID => $branchName)
|
||||
{
|
||||
if(isset($linkedProducts[$productID]) and isset($linkedBranches[$productID][$branchID])) continue;
|
||||
|
||||
$otherProducts["{$productID}_{$branchID}"] = $productName . '_' . $branchName;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isset($linkedProducts[$productID])) continue;
|
||||
$otherProducts[$productID] = $productName;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$currentProducts += $programProducts;
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->currentProducts = $currentProducts;
|
||||
$this->view->otherProducts = $otherProducts;
|
||||
}
|
||||
|
||||
/* Assign. */
|
||||
$this->view->title = $this->lang->project->manageProducts . $this->lang->colon . $project->name;
|
||||
$this->view->project = $project;
|
||||
$this->view->linkedProducts = $linkedProducts;
|
||||
$this->view->linkedBranches = $linkedBranches;
|
||||
$this->view->branches = $branches;
|
||||
$this->view->project = $project;
|
||||
$this->view->unmodifiableProducts = $unmodifiableProducts;
|
||||
$this->view->unmodifiableBranches = $unmodifiableBranches;
|
||||
$this->view->unmodifiableMainBranches = $unmodifiableMainBranches;
|
||||
$this->view->branchGroups = $branchGroups;
|
||||
$this->view->executions = $executions;
|
||||
$this->view->allBranches = $this->branch->getByProducts(array_keys($allProducts), 'ignoreNormal');
|
||||
$this->view->allProducts = $allProducts;
|
||||
|
||||
$this->display();
|
||||
$this->projectZen->dealLinkProduct($projectID, $project);
|
||||
$this->projectZen->buildMangedProductForm($projectID, $project, $executions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取项目页面中下拉执行列表
|
||||
* AJAX: get executions of a project in html select.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $projectID
|
||||
* @param int $executionID
|
||||
* @param string $mode
|
||||
* @param string $type all|sprint|stage|kanban
|
||||
* @param string $type all|sprint|stage|kanban
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetExecutions($projectID, $executionID = 0, $mode = '', $type = 'all')
|
||||
public function ajaxGetExecutions(string $projectID, int $executionID = 0, string $mode = '', string $type = 'all'): mixed
|
||||
{
|
||||
$project = $this->project->getById($projectID);
|
||||
$project = $this->project->getByID($projectID);
|
||||
$disabled = $project->multiple ? '' : 'disabled';
|
||||
$executions = array('' => '') + $this->loadModel('execution')->getPairs($projectID, $type, $mode);
|
||||
|
||||
if($this->app->getViewType() == 'json') return print(json_encode($executionList));
|
||||
if($this->app->getViewType() == 'json') return print(json_encode($executions));
|
||||
|
||||
$disabled = $project->multiple ? '' : 'disabled';
|
||||
return print(html::select('execution', $executions, $executionID, "class='form-control $disabled' $disabled"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据执行ID获取对应的项目下拉列表
|
||||
* AJAX: get a project by execution id.
|
||||
*
|
||||
* @param string $executionID
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function ajaxGetPairsByExecution($executionID)
|
||||
public function ajaxGetPairsByExecution(string $executionID): string
|
||||
{
|
||||
$execution = $this->loadModel('execution')->getByID($executionID);
|
||||
$execution = $this->loadModel('execution')->getByID((int)$executionID);
|
||||
$projectPairs = $this->loadModel('project')->getPairsByIdList($execution->project);
|
||||
|
||||
if($this->app->getViewType() == 'json')
|
||||
|
||||
@@ -488,4 +488,19 @@ class projectTao extends projectModel
|
||||
|
||||
return $parentProgram;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将旧的产品替换成新的
|
||||
* replace oldProduct
|
||||
*
|
||||
* @param array $executionIDs
|
||||
*
|
||||
* @access protected
|
||||
* @return bool
|
||||
*/
|
||||
protected function replaceOldProduct(array $executionIDs): bool
|
||||
{
|
||||
$oldExecutionProducts = $this->dao->select('project,product')->from(TABLE_PROJECTPRODUCT)->where('project')->in($executionIDs)->fetchGroup('project', 'product');
|
||||
return !dao::isError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,32 +6,38 @@ su('admin');
|
||||
|
||||
function initData()
|
||||
{
|
||||
#scrum
|
||||
#project1 对应product1 对应execution1,3 对应文档库2
|
||||
#project3 对应product2,3 对应execution2,4 对应文档库3
|
||||
|
||||
#waterfall
|
||||
#kanban/stage
|
||||
#无迭代项目
|
||||
|
||||
$project = zdTable('project')->config('project')->gen(5);
|
||||
$project = zdTable('project')->config('project')->gen(6);
|
||||
|
||||
$product = zdTable('product');
|
||||
$product->id->range('1-3');
|
||||
$product->gen(3);
|
||||
|
||||
$projectproduct = zdTable('projectproduct')->config('projectproduct')->gen(3);
|
||||
$projectproduct = zdTable('projectproduct')->config('projectproduct')->gen(5);
|
||||
|
||||
$doclib = zdTable('doclib');
|
||||
$doclib->id->range('1');
|
||||
$doclib->execution->range('2');
|
||||
$doclib->project->range('1');
|
||||
$doclib->gen(1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
title=测试 projectModel->deleteByTableName();
|
||||
timeout=0
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
- #删除项目编号为1,同时删除项目下文档库 @1
|
||||
|
||||
- #删除项目编号为1,同时删除项目下的一个执行1-2 @1
|
||||
|
||||
- #删除项目编号为3,同时删除项目下的全部执行3-4 3-5 @1
|
||||
|
||||
- #删除项目编号为1,同时删除项目下关联的第一个产品 @1
|
||||
|
||||
- #删除项目编号为1,同时删除项目下关联的全部产品 @1
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
@@ -40,14 +46,18 @@ $tester->loadModel('project');
|
||||
|
||||
initData();
|
||||
|
||||
$executions = $tester->loadModel('execution')->getPairs(1);
|
||||
$project1 = $tester->project->deleteByTableName('zt_doclib', 2);
|
||||
$project2 = $tester->project->deleteByTableName('zt_product', 2);
|
||||
$project3 = $tester->project->deleteByTableName('zt_project', 2);
|
||||
$project4 = $tester->project->deleteByTableName('zt_project', $executions);
|
||||
$execution = $tester->loadModel('execution')->getPairs(1);
|
||||
$executions = $tester->loadModel('execution')->getPairs(3);
|
||||
$product = $tester->loadModel('product')->getProductIDByProject(1);
|
||||
$products = $tester->loadModel('product')->getProductIDByProject(1, false);
|
||||
$project1 = $tester->project->deleteByTableName('zt_doclib', 1);
|
||||
$project2 = $tester->project->deleteByTableName('zt_project', array_keys($execution));
|
||||
$project3 = $tester->project->deleteByTableName('zt_project', array_keys($executions));
|
||||
$project4 = $tester->project->deleteByTableName('zt_product', $product);
|
||||
$project5 = $tester->project->deleteByTableName('zt_product', $products);
|
||||
|
||||
a($project1);die;
|
||||
r($project1) && p('1:program,name') && e('1,正常产品1'); #删除项目编号为2,同时删除项目下文档库
|
||||
r($project2) && p('2:program,name') && e('1,正常产品2'); #删除项目编号为2,同时删除项目下的一个产品
|
||||
r($project3) && p('3:program,name') && e('1,正常产品3'); #删除项目编号为2,同时删除项目下的一个执行
|
||||
r($project4) && p('4:program,name') && e('1,正常产品4'); #删除项目编号为1,同时删除项目下关联的全部产品
|
||||
r($project1) && p() && e(1); #删除项目编号为1,同时删除项目下文档库
|
||||
r($project2) && p() && e(1); #删除项目编号为1,同时删除项目下的一个执行1-2
|
||||
r($project3) && p() && e(1); #删除项目编号为3,同时删除项目下的全部执行3-4 3-5
|
||||
r($project4) && p() && e(1); #删除项目编号为1,同时删除项目下关联的第一个产品
|
||||
r($project5) && p() && e(1); #删除项目编号为1,同时删除项目下关联的全部产品
|
||||
@@ -3,8 +3,8 @@
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
su('admin');
|
||||
|
||||
$project = zdTable('project');
|
||||
$project->gen(5);
|
||||
$project = zdTable('project')->config('project');
|
||||
$project->gen(4);
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ title=测试 projectModel->getListByCurrentUser();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 执行projectModel模块的getListByCurrentUser方法 @1
|
||||
- 执行projectModel模块的getListByCurrentUser方法 @0
|
||||
|
||||
- 执行projectModel模块的getListByCurrentUser方法 @1
|
||||
|
||||
@@ -27,6 +27,9 @@ cid=1
|
||||
global $tester;
|
||||
$projectModel = $tester->loadModel('project');
|
||||
|
||||
r(count($projectModel->getListByCurrentUser())) && p() && e('1');
|
||||
$tester->app->user->admin = true;
|
||||
$tester->app->config->vision = 'lite';
|
||||
r(count($projectModel->getListByCurrentUser())) && p() && e('0');
|
||||
$tester->app->config->vision = 'rnd';
|
||||
r(count($projectModel->getListByCurrentUser())) && p() && e('1');
|
||||
r($projectModel->getListByCurrentUser()) && p('11:id,name') && e('11,项目1');
|
||||
@@ -3,16 +3,22 @@ author: liuhong
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-5
|
||||
range: 1-6
|
||||
- field: project
|
||||
range: 0, 1, 0, 3, 3
|
||||
range: 0, 1, 0, 3, 3, 0
|
||||
- field: model
|
||||
range: 'scrum, ,waterfall, , ,'
|
||||
range: 'scrum, ,waterfall, , ,scrum'
|
||||
- field: type
|
||||
range: 'project,sprint,project,stage,stage'
|
||||
range: 'project,sprint,project,stage,stage,project'
|
||||
- field: status
|
||||
range: 'wait,doing,closed,suspended'
|
||||
- field: parent
|
||||
range: 0, 1, 0, 3, 3
|
||||
range: 0, 1, 0, 3, 3, 0
|
||||
- field: path
|
||||
range: `,1,`, `,1,2,`, `,3,`, `,3,4,`, `,3,4,5,`
|
||||
range: '`,1,`, `,1,2,`, `,3,`, `,3,4,`, `,3,4,5,`, `,6,`'
|
||||
- field: hasProduct
|
||||
range: 1, 1, 1, 1, 1, 0
|
||||
- field: name
|
||||
range: '项目1, 执行1-2, 项目3, 执行3-4, 执行3-5, 无迭代无产品项目6'
|
||||
- field: code
|
||||
range: 'project1, sprint1-2, project3, sprint3-4, sprint3-5, project6'
|
||||
|
||||
@@ -3,6 +3,6 @@ author: liuhong
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: project
|
||||
range: 1{1},2{2}
|
||||
range: 1{3},2{2}
|
||||
- field: product
|
||||
range: 1, 2, 3
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
title: zt_project
|
||||
author: liuhong
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: type
|
||||
range: 'project,sprint,project,stage'
|
||||
- field: status
|
||||
range: 'wait,doing,closed,suspended'
|
||||
- field: deleted
|
||||
range: 0,1,1,0
|
||||
- field: vision
|
||||
range: rnd,rnd,rnd,lite
|
||||
- field: openedDate
|
||||
range: "20220101 000000:1W" # 生成从2021年1月1日0时0分0秒到当前时间的数据,步长为1周
|
||||
type: timestamp
|
||||
format: "YY/MM/DD hh:mm:ss"
|
||||
+216
-3
@@ -566,12 +566,11 @@ class projectZen extends project
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param array $changes
|
||||
* @param string $comment
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function responseAfterActivate(int $projectID, array $changes, string $comment): void
|
||||
protected function responseAfterActivate(int $projectID, array $changes): void
|
||||
{
|
||||
if($this->post->comment != '' or !empty($changes))
|
||||
{
|
||||
@@ -637,7 +636,7 @@ class projectZen extends project
|
||||
* 从项目中删除所有关联的产品。
|
||||
* removes all associated products from the be deleted project
|
||||
*
|
||||
* @param object $projectID
|
||||
* @param object $project
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
@@ -651,4 +650,218 @@ class projectZen extends project
|
||||
$this->project->deleteByTableName('zt_product', $productID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理并合并项目下的新旧产品
|
||||
* mergeProducts
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param object $project
|
||||
* @param int|array $executionIDs
|
||||
* @param array $postData
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function mergeProducts(int $projectID, object $project, int|array $executionIDs, array $postData): mixed
|
||||
{
|
||||
$this->loadModel('product');
|
||||
$this->loadModel('execution');
|
||||
|
||||
$oldProducts = $this->product->getProducts($projectID);
|
||||
$this->project->updateProducts($projectID);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
//判断是否为项目型项目并更新关联产品
|
||||
if(empty($project->multiple))
|
||||
{
|
||||
$executionID = $this->execution->getNoMultipleID($projectID);
|
||||
if($executionID) $this->execution->updateProducts($executionID);
|
||||
}
|
||||
|
||||
//将项目下关联的新旧产品合并
|
||||
$newProducts = $this->product->getProducts($projectID);
|
||||
$oldProductIDs = array_keys($oldProducts);
|
||||
$newProductIDs = array_keys($newProducts);
|
||||
$diffProducts = array_merge(array_diff($oldProductIDs, $newProductIDs), array_diff($newProductIDs, $oldProductIDs));
|
||||
if($diffProducts) $this->loadModel('action')->create('project', $projectID, 'Managed', '', !empty($postData->rawdata->products) ? implode(',', $postData->rawdata->products) : '');
|
||||
|
||||
//判断是否为产品型项目并更新关联产品
|
||||
if(empty($project->division))
|
||||
{
|
||||
foreach($executionIDs as $executionID)
|
||||
{
|
||||
$this->execution->updateProducts($executionID);
|
||||
if($diffProducts) $this->loadModel('action')->create('execution', $executionID, 'Managed', '', implode(',', array_keys($newProducts)));
|
||||
}
|
||||
}
|
||||
|
||||
//处理非瀑布及产品型项目
|
||||
$this->dealExecutionProduct($project, $oldProducts, $newProductIDs, $executionIDs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理项目执行下关联产品
|
||||
* deal execution product
|
||||
*
|
||||
* @param object $project
|
||||
* @param object $oldProducts
|
||||
* @param array $newProductIDs
|
||||
* @param int|array $executionIDs
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function dealExecutionProduct(object $project, object $oldProducts, array $newProductIDs, array $executionIDs): void
|
||||
{
|
||||
//处理非瀑布及产品型项目
|
||||
if($project->multiple and $project->model != 'waterfall' and $project->model != 'waterfallplus')
|
||||
{
|
||||
$oldExecutionProducts = $this->projectTao->replaceOldProduct($executionIDs);
|
||||
$unlinkedProducts = array_diff(array_keys($oldProducts), $newProductIDs);
|
||||
if(!empty($unlinkedProducts))
|
||||
{
|
||||
$unlinkedProductPairs = array();
|
||||
foreach($unlinkedProducts as $unlinkedProduct) $unlinkedProductPairs[$unlinkedProduct] = $oldProducts[$unlinkedProduct]->name;
|
||||
|
||||
$unlinkExecutions = array();
|
||||
foreach($oldExecutionProducts as $executionID => $executionProducts)
|
||||
{
|
||||
$unlinkExecutionProducts = array_intersect_key($unlinkedProductPairs, $executionProducts);
|
||||
if($unlinkExecutionProducts) $unlinkExecutions[$executionID] = $unlinkExecutionProducts;
|
||||
}
|
||||
|
||||
foreach($unlinkExecutions as $executionID => $unlinkExecutionProducts) $this->loadModel('action')->create('execution', $executionID, 'unlinkproduct', '', implode(',', $unlinkExecutionProducts));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理项目关联需求的产品
|
||||
* dealLinkProduct
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param object $project
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function dealLinkProduct(int $projectID, object $project): void
|
||||
{
|
||||
$this->loadModel('product');
|
||||
$this->loadModel('program');
|
||||
|
||||
$linkedBranches = array();
|
||||
$linkedBranchIdList = array();
|
||||
$branches = $this->project->getBranchesByProject($projectID);
|
||||
$linkedProductIdList = empty($branches) ? '' : array_keys($branches);
|
||||
$allProducts = $this->program->getProductPairs($project->parent, 'all', 'noclosed', $linkedProductIdList);
|
||||
$linkedProducts = $this->product->getProducts($projectID, 'all', '', true, $linkedProductIdList);
|
||||
$projectStories = $this->project->getStoriesByProject($projectID);
|
||||
$projectBranches = $this->project->getBranchGroupByProject($projectID, array_keys($linkedProducts));
|
||||
$branchGroups = $this->loadModel('branch')->getByProducts(array_keys($allProducts), 'ignoreNormal|noclosed', $linkedBranchIdList);
|
||||
|
||||
/* If the story of the product which linked the project,don't allow to remove the product. */
|
||||
$unmodifiableProducts = array();
|
||||
$unmodifiableBranches = array();
|
||||
$unmodifiableMainBranches = array();
|
||||
foreach($linkedProducts as $productID => $linkedProduct)
|
||||
{
|
||||
$linkedBranches[$productID] = array();
|
||||
foreach($branches[$productID] as $branchID => $branch)
|
||||
{
|
||||
$linkedBranches[$productID][$branchID] = $branchID;
|
||||
$linkedBranchIdList[$branchID] = $branchID;
|
||||
|
||||
if(!empty($projectStories[$productID][$branchID]) or !empty($projectBranches[$productID][$branchID]))
|
||||
{
|
||||
if($branchID == BRANCH_MAIN) $unmodifiableMainBranches[$productID] = $branchID;
|
||||
array_push($unmodifiableProducts, $productID);
|
||||
array_push($unmodifiableBranches, $branchID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->dealOtherLinkProduct($project, $branchGroups, $linkedBranches);
|
||||
|
||||
$this->view->allBranches = $this->loadModel('branch')->getByProducts(array_keys($allProducts), 'ignoreNormal');
|
||||
$this->view->allProducts = $allProducts;
|
||||
$this->view->unmodifiableProducts = $unmodifiableProducts;
|
||||
$this->view->unmodifiableBranches = $unmodifiableBranches;
|
||||
$this->view->unmodifiableMainBranches = $unmodifiableMainBranches;
|
||||
$this->view->linkedBranches = $linkedBranches;
|
||||
$this->view->branchGroups = $branchGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* dealOtherLinkProduct
|
||||
*
|
||||
* @param object $project
|
||||
* @param object $branchGroups
|
||||
* @param array $linkedBranches
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function dealOtherLinkProduct(object $project, object $branchGroups, array $linkedBranches): void
|
||||
{
|
||||
$linkedProducts = $this->product->getProducts($projectID, 'all', '', true, $linkedProductIdList);
|
||||
|
||||
if($this->config->systemMode == 'ALM')
|
||||
{
|
||||
$topProgramID = $project->parent ? $this->program->getTopByPath($project->path) : 0;
|
||||
$productsGroupByProgram = $this->product->getProductsGroupByProgram();
|
||||
|
||||
$currentProducts = array();
|
||||
$otherProducts = array();
|
||||
foreach($productsGroupByProgram as $programID => $programProducts)
|
||||
{
|
||||
if($programID != $topProgramID)
|
||||
{
|
||||
foreach($programProducts as $productID => $productName)
|
||||
{
|
||||
if(!empty($branchGroups[$productID]))
|
||||
{
|
||||
foreach($branchGroups[$productID] as $branchID => $branchName)
|
||||
{
|
||||
if(isset($linkedProducts[$productID]) and isset($linkedBranches[$productID][$branchID])) continue;
|
||||
|
||||
$otherProducts["{$productID}_{$branchID}"] = $productName . '_' . $branchName;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isset($linkedProducts[$productID])) continue;
|
||||
$otherProducts[$productID] = $productName;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$currentProducts += $programProducts;
|
||||
}
|
||||
}
|
||||
$this->view->currentProducts = $currentProducts;
|
||||
$this->view->otherProducts = $otherProducts;
|
||||
}
|
||||
$this->view->linkedProducts = $linkedProducts;
|
||||
}
|
||||
|
||||
/**
|
||||
* buildMangedProductForm
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param object $project
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function buildMangedProductForm(int $projectID, $project, $executions): void
|
||||
{
|
||||
$this->view->title = $this->lang->project->manageProducts . $this->lang->colon . $project->name;
|
||||
$this->view->project = $project;
|
||||
$this->view->executions = $executions;
|
||||
$this->view->branches = $this->project->getBranchesByProject($projectID);
|
||||
$this->display();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2399,7 +2399,7 @@ class story extends control
|
||||
public function tasks($storyID, $executionID = 0)
|
||||
{
|
||||
$this->loadModel('task');
|
||||
$tasks = $this->task->getStoryTasks($storyID, $executionID);
|
||||
$tasks = $this->task->getListByStory($storyID, $executionID);
|
||||
$this->view->tasks = $tasks;
|
||||
$this->view->users = $this->user->getPairs('noletter');
|
||||
$this->view->summary = $this->execution->summary($tasks);
|
||||
|
||||
@@ -5463,7 +5463,7 @@ class storyModel extends model
|
||||
$stories[$id]->title = $story->title;
|
||||
$stories[$id]->cases = $this->loadModel('testcase')->getStoryCases($id);
|
||||
$stories[$id]->bugs = $this->loadModel('bug')->getStoryBugs($id);
|
||||
$stories[$id]->tasks = $this->loadModel('task')->getStoryTasks($id);
|
||||
$stories[$id]->tasks = $this->loadModel('task')->getListByStory($id);
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
$stories[$id]->designs = $this->dao->select('id, name')->from(TABLE_DESIGN)
|
||||
@@ -5537,7 +5537,7 @@ class storyModel extends model
|
||||
$stories[$id]->title = $story->title;
|
||||
$stories[$id]->cases = $this->loadModel('testcase')->getStoryCases($id);
|
||||
$stories[$id]->bugs = $this->loadModel('bug')->getStoryBugs($id);
|
||||
$stories[$id]->tasks = $this->loadModel('task')->getStoryTasks($id, 0, $projectID);
|
||||
$stories[$id]->tasks = $this->loadModel('task')->getListByStory($id, 0, $projectID);
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
$stories[$id]->designs = $this->dao->select('id, name')->from(TABLE_DESIGN)
|
||||
@@ -5581,7 +5581,7 @@ class storyModel extends model
|
||||
$track[$id]->case = $this->loadModel('testcase')->getStoryCases($id);
|
||||
$track[$id]->bug = $this->loadModel('bug')->getStoryBugs($id);
|
||||
$track[$id]->story = $this->getByID($id);
|
||||
$track[$id]->task = $this->loadModel('task')->getStoryTasks($id);
|
||||
$track[$id]->task = $this->loadModel('task')->getListByStory($id);
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
$track[$id]->design = $this->dao->select('id, name')->from(TABLE_DESIGN)
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
su('admin');
|
||||
|
||||
function initData()
|
||||
{
|
||||
$task = zdTable('task');
|
||||
$task->id->range('1-5');
|
||||
$task->name->prefix('任务')->range('1-5');
|
||||
$task->parent->range('`-1`,1,1,0,0');
|
||||
$task->execution->range('6,7,8,9,10');
|
||||
$task->project->range('1,2,3,4,5');
|
||||
|
||||
$task->gen(5);
|
||||
|
||||
$project = zdTable('project');
|
||||
$project->id->range('1-10');
|
||||
$project->name->prefix('project')->range('1-10');
|
||||
$project->project->range('0,0,0,0,0,1,2,3,4,5');
|
||||
|
||||
$project->gen(10);
|
||||
}
|
||||
|
||||
function insertDate($taskID, $estStarted, $deadline)
|
||||
{
|
||||
}
|
||||
|
||||
function getByID($taskID)
|
||||
{
|
||||
global $tester;
|
||||
return $tester->dao->select('estStarted,deadline,lastEditedBy')->from(TABLE_TASK)->where('id')->eq($taskID)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
title=测试updatetaskesdatebygantt
|
||||
cid=1
|
||||
|
||||
*/
|
||||
initData();
|
||||
|
||||
$postData = new stdClass();
|
||||
$postData->id = 1;
|
||||
$postData->startDate = '2023-04-20';
|
||||
$postData->endDate = '2023-04-24';
|
||||
$postData->type = 'task';
|
||||
|
||||
$tester->loadModel('task');
|
||||
|
||||
$taskIDList = range(1,5);
|
||||
$taskList = $tester->task->getByList($taskIDList);
|
||||
|
||||
$tester->task->updateTaskEsDateByGantt($taskIDList[1], $postData);
|
||||
$tester->task->updateTaskEsDateByGantt($taskIDList[2], $postData);
|
||||
$tester->task->updateTaskEsDateByGantt($taskIDList[3], $postData);
|
||||
$tester->task->updateTaskEsDateByGantt($taskIDList[4], $postData);
|
||||
$tester->task->updateTaskEsDateByGantt($taskIDList[5], $postData);
|
||||
@@ -43,3 +43,9 @@ $config->todo->objectList['bug'] = 'bugs';
|
||||
$config->todo->objectList['task'] = 'tasks';
|
||||
$config->todo->objectList['story'] = 'stories';
|
||||
$config->todo->objectList['testtask'] = 'testtasks';
|
||||
|
||||
$config->todo->sessionUri = array();
|
||||
$config->todo->sessionUri['bugList'] = 'qa';
|
||||
$config->todo->sessionUri['taskList'] = 'execution';
|
||||
$config->todo->sessionUri['storyList'] = 'product';
|
||||
$config->todo->sessionUri['testtaskList'] = 'qa';
|
||||
|
||||
@@ -39,4 +39,16 @@ $config->todo->batchClose->form['todoIDList'] = array('required' => true, 'type'
|
||||
$config->todo->batchEdit = new stdClass;
|
||||
$config->todo->batchEdit->form = array();
|
||||
$config->todo->batchEdit->form['todoIDList'] = array('required' => true, 'type' => 'array');
|
||||
$config->todo->batchEdit->form['names'] = array('required' => true, 'type' => 'array');
|
||||
|
||||
$config->todo->batchFinish = new stdclass;
|
||||
$config->todo->batchFinish->form = array();
|
||||
$config->todo->batchFinish->form['todoIDList'] = array('required' => true, 'type' => 'array');
|
||||
|
||||
$config->todo->editDate = new stdClass;
|
||||
$config->todo->editDate->form = array();
|
||||
$config->todo->editDate->form['date'] = array('required' => true, 'type' => 'string');
|
||||
$config->todo->editDate->form['todoIDList'] = array('required' => true, 'type' => 'array');
|
||||
|
||||
$config->todo->export = new stdClass;
|
||||
$config->todo->export->form = array();
|
||||
$config->todo->export->form['exportType'] = array('required' => true, 'type' => 'string');
|
||||
+101
-128
@@ -35,9 +35,9 @@ class todo extends control
|
||||
* @param string $date
|
||||
* @param string $from todo|feedback|block
|
||||
* @access public
|
||||
* @return int
|
||||
* @return void
|
||||
*/
|
||||
public function create(string $date = 'today', string $from = 'todo'): int
|
||||
public function create(string $date = 'today', string $from = 'todo')
|
||||
{
|
||||
if($date == 'today') $date = date::today();
|
||||
|
||||
@@ -46,11 +46,11 @@ class todo extends control
|
||||
$formData = form::data($this->config->todo->create->form);
|
||||
$todo = $this->todoZen->beforeCreate($formData);
|
||||
|
||||
$todoID = $this->todo->create($todo);
|
||||
$todoID = $this->todo->create($todo, $formData);
|
||||
if($todoID === false) return print(js::error(dao::getError()));
|
||||
|
||||
$todo->id = $todoID;
|
||||
$this->todoZen->afterCreate($todo);
|
||||
$this->todoZen->afterCreate($todo, $formData);
|
||||
|
||||
if(!empty($_POST['objectID'])) return $this->send(array('result' => 'success'));
|
||||
|
||||
@@ -64,12 +64,12 @@ class todo extends control
|
||||
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $todoID));
|
||||
if($this->viewType == 'xhtml') return print(js::locate($this->createLink('todo', 'view', "todoID=$todoID", 'html'), 'parent'));
|
||||
if(isonlybody()) return print(js::closeModal('parent.parent'));
|
||||
return print(js::locate($this->createLink('my', 'todo', "type=all&userID=&status=all&orderBy=id_desc"), 'parent'));
|
||||
return print(js::locate($this->createLink('my', 'todo', 'type=all&userID=&status=all&orderBy=id_desc'), 'parent'));
|
||||
}
|
||||
|
||||
unset($this->lang->todo->typeList['cycle']);
|
||||
|
||||
$this->buildCreateView($date);
|
||||
$this->todoZen->buildCreateView($date);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,19 +173,24 @@ class todo extends control
|
||||
*
|
||||
* @param string $from example:myTodo, todoBatchEdit.
|
||||
* @param string $type
|
||||
* @param int $userID
|
||||
* @param string $userID
|
||||
* @param string $status
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function batchEdit(string $from = '', string $type = 'today', string $userID = '', string $status = 'all')
|
||||
{
|
||||
$formData = form::data($this->config->todo->batchEdit->form);
|
||||
$userID = (int)$userID;
|
||||
|
||||
/* Get form data for my-todo. */
|
||||
if($from == 'myTodo') $this->todoZen->batchEditFromMyTodo($type, $userID, $status);
|
||||
if($from == 'myTodo') $this->todoZen->batchEditFromMyTodo($formData, $type, $userID, $status);
|
||||
if($from == 'todoBatchEdit')
|
||||
{
|
||||
$formData = form::data($this->config->todo->batchEdit->form);
|
||||
$this->todoZen->batchEditFromTodoBatchEdit($formData);
|
||||
$todos = $this->todoZen->beforeBatchEdit($formData);
|
||||
$allChanges = $this->todo->batchUpdate($todos, $formData->data->todoIDList);
|
||||
$this->todoZen->afterBatchEdit($allChanges);
|
||||
|
||||
return print(js::locate($this->session->todoList, 'parent'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +209,7 @@ class todo extends control
|
||||
|
||||
if($todo->status == 'wait')
|
||||
{
|
||||
this->todo->start($todoID);
|
||||
$this->todo->start($todoID);
|
||||
if(dao::isError()) return print(js::error(dao::getError()));
|
||||
}
|
||||
if(in_array($todo->type, array('bug', 'task', 'story'))) return $this->todoZen->printStartConfirm($todo);
|
||||
@@ -258,7 +263,7 @@ class todo extends control
|
||||
if(defined('RUN_MODE') && RUN_MODE == 'api')
|
||||
{
|
||||
$this->send(array('status' => 'success'));
|
||||
return;
|
||||
return 1; /* A function with return type must return a value. */
|
||||
}
|
||||
|
||||
if(isonlybody()) return print(js::reload('parent.parent'));
|
||||
@@ -272,9 +277,9 @@ class todo extends control
|
||||
*
|
||||
* @param string $todoID
|
||||
* @access public
|
||||
* @return int
|
||||
* @return void
|
||||
*/
|
||||
public function assignTo(string $todoID): int
|
||||
public function assignTo(string $todoID)
|
||||
{
|
||||
$todoID = (int)$todoID;
|
||||
if(!empty($_POST))
|
||||
@@ -289,13 +294,7 @@ class todo extends control
|
||||
return print(js::reload('parent.parent'));
|
||||
}
|
||||
|
||||
$this->view->todo = $this->todo->getByID($todoID);
|
||||
$this->view->members = $this->loadModel('user')->getPairs('noclosed|noempty|nodeleted');
|
||||
$this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
|
||||
$this->view->actions = $this->loadModel('action')->getList('todo', $todoID);
|
||||
$this->view->users = $this->user->getPairs('noletter');
|
||||
$this->view->time = date::now();
|
||||
$this->display();
|
||||
$this->todoZen->buildAssignToView($todoID);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -306,9 +305,9 @@ class todo extends control
|
||||
* @param string $from my|company
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @return int
|
||||
*/
|
||||
public function view(string $todoID, string $from = 'company')
|
||||
public function view(string $todoID, string $from = 'company'): int
|
||||
{
|
||||
$todo = $this->todo->getByID((int)$todoID, true);
|
||||
|
||||
@@ -321,15 +320,7 @@ class todo extends control
|
||||
$account = $this->app->user->account;
|
||||
if($todo->private and $todo->account != $account) return print(js::error((string)$this->lang->todo->thisIsPrivate) . (string)js::locate('back'));
|
||||
|
||||
/* Save the session. */
|
||||
if(!isonlybody())
|
||||
{
|
||||
$url = $this->app->getURI(true);
|
||||
$this->session->set('bugList', $url, 'qa');
|
||||
$this->session->set('taskList', $url, 'execution');
|
||||
$this->session->set('storyList', $url, 'product');
|
||||
$this->session->set('testtaskList', $url, 'qa');
|
||||
}
|
||||
if(!isonlybody()) $this->todoZen->setSessionUri($this->app->getURI(true));
|
||||
|
||||
/* Fix bug #936. */
|
||||
if($account != $todo->account and $account != $todo->assignedTo and !common::hasPriv('my', 'team'))
|
||||
@@ -341,6 +332,7 @@ class todo extends control
|
||||
if(!isset($this->session->project)) $this->session->set('project', (int)key($projects));
|
||||
|
||||
$this->todoZen->buildAssignToTodoView((object)$todo, (int)$this->session->project, (array)$projects, (string)$account, $from);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -350,36 +342,30 @@ class todo extends control
|
||||
* @param string $todoID
|
||||
* @param string $confirm yes|no
|
||||
* @access public
|
||||
* @return void
|
||||
* @return int
|
||||
*/
|
||||
public function delete(string $todoID, string $confirm = 'no')
|
||||
public function delete(string $todoID, string $confirm = 'no'): int
|
||||
{
|
||||
$todoID = (int)$todoID;
|
||||
if($confirm == 'no')
|
||||
{
|
||||
return print(js::confirm($this->lang->todo->confirmDelete, $this->createLink('todo', 'delete', "todoID={$todoID}&confirm=yes")));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->todo->delete(TABLE_TODO, $todoID);
|
||||
if($confirm == 'no') return print(js::confirm($this->lang->todo->confirmDelete, $this->createLink('todo', 'delete', "todoID={$todoID}&confirm=yes")));
|
||||
$this->todo->delete(TABLE_TODO, $todoID);
|
||||
|
||||
if(helper::isAjaxRequest())
|
||||
if(helper::isAjaxRequest())
|
||||
{
|
||||
$response = array('result' => 'success', 'message' => '');
|
||||
if(dao::isError())
|
||||
{
|
||||
$response = array('result' => 'success', 'message' => '');
|
||||
if(dao::isError())
|
||||
{
|
||||
$response['result'] = 'fail';
|
||||
$response['message'] = dao::getError();
|
||||
}
|
||||
return $this->send($response);
|
||||
$response['result'] = 'fail';
|
||||
$response['message'] = dao::getError();
|
||||
}
|
||||
|
||||
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success'));
|
||||
if(isonlybody()) return print(js::reload('parent.parent'));
|
||||
|
||||
$browseLink = $this->session->todoList ? $this->session->todoList : $this->createLink('my', 'todo');
|
||||
return print(js::locate($browseLink, 'parent'));
|
||||
return $this->send($response);
|
||||
}
|
||||
|
||||
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success'));
|
||||
if(isonlybody()) return print(js::reload('parent.parent'));
|
||||
|
||||
$browseLink = $this->session->todoList ? $this->session->todoList : $this->createLink('my', 'todo');
|
||||
return print(js::locate($browseLink, 'parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -388,14 +374,21 @@ class todo extends control
|
||||
*
|
||||
* @param string $todoID
|
||||
* @access public
|
||||
* @return void
|
||||
* @return int|false
|
||||
*/
|
||||
public function finish(string $todoID)
|
||||
public function finish(string $todoID): int|false
|
||||
{
|
||||
$todo = $this->todo->getByID((int)$todoID);
|
||||
if($todo->status != 'done' && $todo->status != 'closed') $this->todo->finish((int)$todoID);
|
||||
$todoID = (int)$todoID;
|
||||
$todo = $this->todo->getByID($todoID);
|
||||
if($todo->status != 'done' && $todo->status != 'closed')
|
||||
{
|
||||
$result = $this->todo->finish($todoID);
|
||||
if(!$result) return false;
|
||||
}
|
||||
|
||||
if(in_array($todo->type, array('bug', 'task', 'story')))
|
||||
$types = $this->config->todo->moduleList;
|
||||
array_pop($types);
|
||||
if(in_array($todo->type, $types))
|
||||
{
|
||||
$confirmNote = 'confirm' . ucfirst($todo->type);
|
||||
$okTarget = isonlybody() ? 'parent' : 'window.parent.$.apps.open';
|
||||
@@ -404,6 +397,7 @@ class todo extends control
|
||||
if($todo->type == 'bug') $app = 'qa';
|
||||
if($todo->type == 'task') $app = 'execution';
|
||||
if($todo->type == 'story') $app = 'product';
|
||||
|
||||
$cancelURL = $this->server->http_referer;
|
||||
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success', 'message' => sprintf($this->lang->todo->$confirmNote, $todo->objectID), 'locate' => $confirmURL));
|
||||
return print(strpos($cancelURL, 'calendar') ? json_encode(array(sprintf($this->lang->todo->$confirmNote, $todo->objectID), $confirmURL)) : js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->objectID), $confirmURL, $cancelURL, $okTarget, 'parent', $app));
|
||||
@@ -411,11 +405,10 @@ class todo extends control
|
||||
|
||||
if(defined('RUN_MODE') && RUN_MODE == 'api')
|
||||
{
|
||||
$this->send(array('status' => 'success'));
|
||||
return;
|
||||
return $this->send(array('status' => 'success'));
|
||||
}
|
||||
if(isonlybody()) return print(js::reload('parent.parent'));
|
||||
echo js::reload('parent');
|
||||
return print(js::reload('parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -423,23 +416,21 @@ class todo extends control
|
||||
* Batch finish todos.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @return int|false
|
||||
*/
|
||||
public function batchFinish()
|
||||
public function batchFinish(): int|false
|
||||
{
|
||||
if($this->post->todoIDList)
|
||||
$todoIDList = form::data($this->config->todo->batchFinish->form)->get('todoIDList');
|
||||
$todoList = $this->todo->getByList($todoIDList);
|
||||
foreach($todoList as $todoID => $todo)
|
||||
{
|
||||
$todoList = $this->todo->getByList((array)$this->post->todoIDList);
|
||||
foreach($todoList as $todoID => $todo)
|
||||
{
|
||||
if($todo->status == 'done' || $todo->status == 'closed') unset($todoList[$todoID]);
|
||||
}
|
||||
|
||||
$isBatchFinished = $this->todo->batchFinish(array_keys($todoList));
|
||||
if(!$isBatchFinished) return false;
|
||||
|
||||
return print(js::reload('parent'));
|
||||
if($todo->status == 'done' || $todo->status == 'closed') unset($todoList[$todoID]);
|
||||
}
|
||||
|
||||
$isBatchFinished = $this->todo->batchFinish(array_keys($todoList));
|
||||
if(!$isBatchFinished) return false;
|
||||
|
||||
return print(js::reload('parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -473,18 +464,21 @@ class todo extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function import2Today(string $todoID = '')
|
||||
public function import2Today(string $todoID = ''): void
|
||||
{
|
||||
$todoIDList = $_POST ? $this->post->todoIDList : array($todoID);
|
||||
$date = !empty($_POST['date']) ? $_POST['date'] : date::today();
|
||||
if(!$date || !$todoIDList) return $this->locate((string)$this->session->todoList);
|
||||
if(!$_POST) $this->locate($this->createLink('my', 'todo'));
|
||||
|
||||
$formData = form::data($this->config->todo->editDate->form);
|
||||
$todoIDList = !empty($formData->rawdata->todoIDList) ? $formData->rawdata->todoIDList : array($todoID);
|
||||
$date = !empty($formData->rawdata->date) ? $formData->rawdata->date : date::today();
|
||||
if(!$todoIDList) $this->locate((string)$this->session->todoList);
|
||||
|
||||
$this->todo->editDate((array)$todoIDList, (string)$date);
|
||||
return $this->locate((string)$this->session->todoList);
|
||||
$this->locate((string)$this->session->todoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data to export
|
||||
* Get data to export.
|
||||
*
|
||||
* @param int $userID
|
||||
* @param string $orderBy
|
||||
@@ -495,57 +489,35 @@ class todo extends control
|
||||
{
|
||||
if($_POST)
|
||||
{
|
||||
$user = $this->loadModel('user')->getById($userID, 'id');
|
||||
$account = $user->account;
|
||||
$todoLang = $this->lang->todo;
|
||||
$user = $this->todoZen->getUserById((int)$userID);
|
||||
$account = (string)$user->account;
|
||||
$todoLang = (object)$this->lang->todo;
|
||||
$configTime = $this->config->todo->times;
|
||||
|
||||
/* Create field lists. */
|
||||
$fields = $this->todoZen->exportFields(explode(',', $this->config->todo->list->exportFields), (object)$todoLang);
|
||||
$formData = form::data($this->config->todo->export->form);
|
||||
$todos = $this->todo->getByExportList($orderBy, (object)$formData);
|
||||
|
||||
/* Get bugs. */
|
||||
$todos = $this->dao->select('*')->from(TABLE_TODO)->where($this->session->todoReportCondition)
|
||||
->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi()
|
||||
->orderBy($orderBy)->fetchAll('id');
|
||||
list($todos, $fields) = $this->todoZen->exportTodoInfo((array)$todos, (string)$this->config->todo->list->exportFields, $todoLang);
|
||||
list($users, $bugs, $stories, $tasks, $testTasks) = $this->todoZen->exportAssociated('default', $account);
|
||||
|
||||
/* Get users, bugs, tasks and times. */
|
||||
list($users, $bugs, $stories, $tasks, $testTasks) = $this->todoZen->exportInfo('default', $account);
|
||||
$times = date::buildTimeList((int)$configTime->begin, (int)$configTime->end, (int)$configTime->delta);
|
||||
|
||||
if($this->config->edition == 'max') list($issues, $risks, $opportunities) = $this->todoZen->exportInfo($this->config->edition, $account);
|
||||
|
||||
if(isset($this->config->qcVersion)) $reviews = $this->todoZen->exportInfo('qcVersion', $account);
|
||||
$times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
|
||||
|
||||
foreach($todos as $todo)
|
||||
$assemble = new stdClass();
|
||||
$assemble->users = $users;
|
||||
$assemble->bugs = $bugs;
|
||||
$assemble->stories = $stories;
|
||||
$assemble->tasks = $tasks;
|
||||
$assemble->testTasks = $testTasks;
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
/* fill some field with useful value. */
|
||||
$todo->begin = $todo->begin == '2400' ? '' : (isset($times[$todo->begin]) ? $times[$todo->begin] : $todo->begin);
|
||||
$todo->end = $todo->end == '2400' ? '' : (isset($times[$todo->end]) ? $times[$todo->end] : $todo->end);
|
||||
|
||||
$type = $todo->type;
|
||||
if(isset($users[$todo->account])) $todo->account = $users[$todo->account];
|
||||
if($type == 'bug') $todo->name = isset($bugs[$todo->objectID]) ? $bugs[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
if($type == 'story') $todo->name = isset($stories[$todo->objectID]) ? $stories[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
if($type == 'task') $todo->name = isset($tasks[$todo->objectID]) ? $tasks[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
if($type == 'issue') $todo->name = isset($issues[$todo->objectID]) ? $issues[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
if($type == 'risk') $todo->name = isset($risks[$todo->objectID]) ? $risks[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
if($type == 'opportunity') $todo->name = isset($opportunities[$todo->objectID]) ? $opportunities[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
}
|
||||
if($type == 'testtask') $todo->name = isset($testTasks[$todo->objectID]) ? $testTasks[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
if($type == 'review' && isset($this->config->qcVersion)) $todo->name = isset($reviews[$todo->objectID]) ? $reviews[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
|
||||
if(isset($todoLang->typeList[$type])) $todo->type = $todoLang->typeList[$type];
|
||||
if(isset($todoLang->priList[$todo->pri])) $todo->pri = $todoLang->priList[$todo->pri];
|
||||
if(isset($todoLang->statusList[$todo->status])) $todo->status = $todoLang->statusList[$todo->status];
|
||||
if($todo->private == 1) $todo->desc = $this->lang->todo->thisIsPrivate;
|
||||
|
||||
/* drop some field that is not needed. */
|
||||
unset($todo->objectID);
|
||||
unset($todo->private);
|
||||
$iroData = $this->todoZen->exportInfo((string)$this->config->edition, $account);
|
||||
$assemble->issues = $iroData[0];
|
||||
$assemble->risks = $iroData[1];
|
||||
$assemble->opportunities = $iroData[2];
|
||||
}
|
||||
if($this->config->edition != 'open') list($fields, $todos) = $this->loadModel('workflowfield')->appendDataFromFlow($fields, $todos);
|
||||
if(isset($this->config->qcVersion)) $assemble->reviews = $this->todoZen->exportInfo('qcVersion', $account);
|
||||
|
||||
$todos = $this->todoZen->assembleExportData((array)$todos, $assemble, $todoLang, (array)$times);
|
||||
|
||||
$this->post->set('fields', $fields);
|
||||
$this->post->set('rows', $todos);
|
||||
@@ -594,6 +566,7 @@ class todo extends control
|
||||
*/
|
||||
public function ajaxGetExecutionPairs($projectID)
|
||||
{
|
||||
$projectID = (int)$projectID;
|
||||
$this->session->set('project', $projectID);
|
||||
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.form-row .items-center {align-items: center;}
|
||||
.form-row .form-group.pl-3 {padding-left: 0.75rem;}
|
||||
+81
-83
@@ -149,80 +149,43 @@ class todoModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch update todos.
|
||||
* 更新批量编辑待办数据。
|
||||
* Update batch edit todo data.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
* @param array $todos
|
||||
* @param array $todoIdList
|
||||
* @access protected
|
||||
* @return array|int
|
||||
*/
|
||||
public function batchUpdate()
|
||||
public function batchUpdate(array $todos, array $todoIdList): array|int
|
||||
{
|
||||
$todos = array();
|
||||
if(empty($todos)) return $todos;
|
||||
|
||||
$allChanges = array();
|
||||
$data = fixer::input('post')->get();
|
||||
$todoIDList = $this->post->todoIDList ? $this->post->todoIDList : array();
|
||||
|
||||
if(!empty($todoIDList))
|
||||
/* Initialize todos from the post data. */
|
||||
$oldTodos = $this->getTodosByIdList($todoIdList);
|
||||
foreach($todos as $todoID => $todo)
|
||||
{
|
||||
/* Initialize todos from the post data. */
|
||||
$oldTodos = $this->dao->select('*')->from(TABLE_TODO)->where('id')->in(array_keys($todos))->fetchAll('id');
|
||||
foreach($todoIDList as $todoID)
|
||||
$oldTodo = $oldTodos[$todoID];
|
||||
if(in_array($todo->type, $this->config->todo->moduleList)) $oldTodo->name = '';
|
||||
$this->updateTodoDataByID($todoID, $todo);
|
||||
|
||||
if($oldTodo->status != 'done' and $todo->status == 'done') $this->loadModel('action')->create('todo', $todoID, 'finished', '', 'done');
|
||||
|
||||
if(!dao::isError())
|
||||
{
|
||||
$oldTodo = $oldTodos[$todoID];
|
||||
|
||||
$todo = new stdclass();
|
||||
$todo->date = $data->dates[$todoID];
|
||||
$todo->type = $data->types[$todoID];
|
||||
$todo->pri = $data->pris[$todoID];
|
||||
$todo->status = $data->status[$todoID];
|
||||
$todo->name = !in_array($todo->type, $this->config->todo->moduleList) ? $data->names[$todoID] : '';
|
||||
$todo->begin = isset($data->begins[$todoID]) ? $data->begins[$todoID] : 2400;
|
||||
$todo->end = isset($data->ends[$todoID]) ? $data->ends[$todoID] : 2400;
|
||||
$todo->assignedTo = isset($data->assignedTos[$todoID]) ? $data->assignedTos[$todoID] : $oldTodo->assignedTo;
|
||||
|
||||
if(in_array($todo->type, $this->config->todo->moduleList))
|
||||
if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $todo->type == 'feedback' && $todo->objectID && !isset($feedbacks[$todo->objectID]))
|
||||
{
|
||||
$todo->objectID = isset($data->{$this->config->todo->objectList[$todo->type]}[$todoID]) ? $data->{$this->config->todo->objectList[$todo->type]}[$todoID] : 0;
|
||||
$feedbacks[$todo->objectID] = $todo->objectID;
|
||||
$this->loadModel('feedback')->updateStatus('todo', $todo->objectID, $todo->status);
|
||||
}
|
||||
if($todo->end < $todo->begin) return print(js::alert(sprintf($this->lang->error->gt, $this->lang->todo->end, $this->lang->todo->begin)));
|
||||
|
||||
$todos[$todoID] = $todo;
|
||||
$allChanges[$todoID] = common::createChanges($oldTodo, $todo);
|
||||
}
|
||||
|
||||
foreach($todos as $todoID => $todo)
|
||||
else
|
||||
{
|
||||
$oldTodo = $oldTodos[$todoID];
|
||||
if(in_array($todo->type, $this->config->todo->moduleList)) $oldTodo->name = '';
|
||||
$this->dao->update(TABLE_TODO)->data($todo)
|
||||
->autoCheck()
|
||||
->checkIF(!in_array($todo->type, $this->config->todo->moduleList), $this->config->todo->edit->requiredFields, 'notempty')
|
||||
->checkIF($todo->type == 'bug' and $todo->objectID == 0, 'objectID', 'notempty')
|
||||
->checkIF($todo->type == 'task' and $todo->objectID == 0, 'objectID', 'notempty')
|
||||
->checkIF($todo->type == 'story' and $todo->objectID == 0, 'objectID', 'notempty')
|
||||
->checkIF($todo->type == 'issue' and $todo->objectID == 0, 'objectID', 'notempty')
|
||||
->checkIF($todo->type == 'risk' and $todo->objectID == 0, 'objectID', 'notempty')
|
||||
->checkIF($todo->type == 'opportunity' and $todo->objectID == 0, 'objectID', 'notempty')
|
||||
->checkIF($todo->type == 'review' and $todo->objectID == 0, 'objectID', 'notempty')
|
||||
->checkIF($todo->type == 'testtask' and $todo->objectID == 0, 'objectID', 'notempty')
|
||||
->checkIF($todo->type == 'feedback' and $todo->objectID == 0, 'objectID', 'notempty')
|
||||
->where('id')->eq($todoID)
|
||||
->exec();
|
||||
|
||||
if($oldTodo->status != 'done' and $todo->status == 'done') $this->loadModel('action')->create('todo', $todoID, 'finished', '', 'done');
|
||||
|
||||
if(!dao::isError())
|
||||
{
|
||||
if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $todo->type == 'feedback' && $todo->objectID && !isset($feedbacks[$todo->objectID]))
|
||||
{
|
||||
$feedbacks[$todo->objectID] = $todo->objectID;
|
||||
$this->loadModel('feedback')->updateStatus('todo', $todo->objectID, $todo->status);
|
||||
}
|
||||
|
||||
$allChanges[$todoID] = common::createChanges($oldTodo, $todo);
|
||||
}
|
||||
else
|
||||
{
|
||||
return print(js::error('todo#' . $todoID . dao::getError(true)));
|
||||
}
|
||||
return print(js::error('todo#' . $todoID . dao::getError(true)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,44 +541,41 @@ class todoModel extends model
|
||||
*/
|
||||
public function assignTo(object $todo): bool
|
||||
{
|
||||
$res = $this->todoTao->updateRow((int)$todo->id, $todo);
|
||||
if(!$res) return false;
|
||||
$todoID = (int)$todo->id;
|
||||
$result = $this->todoTao->updateRow($todoID, $todo);
|
||||
if(!$result) return false;
|
||||
|
||||
$this->loadModel('action')->create('todo', (int)$todo->id, 'assigned', '', $todo->assignedTo);
|
||||
$this->loadModel('action')->create('todo', $todoID, 'assigned', '', $todo->assignedTo);
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取待办事项的数量。
|
||||
* Get todo count.
|
||||
*
|
||||
* @param string $account
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getCount($account = '')
|
||||
public function getCount(string $account = ''): int
|
||||
{
|
||||
if(empty($account)) $account = $this->app->user->account;
|
||||
return $this->dao->select('count(*) as count')->from(TABLE_TODO)
|
||||
->where('cycle')->eq('0')
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->andWhere('account', true)->eq($account)
|
||||
->orWhere('assignedTo')->eq($account)
|
||||
->orWhere('finishedBy')->eq($account)
|
||||
->markRight(1)
|
||||
->fetch('count');
|
||||
|
||||
return $this->todoTao->getTodoCountByAccount($account);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取待办事项对象的项目ID。
|
||||
* Gets the project ID of the to-do object.
|
||||
*
|
||||
* @param array $todoList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTodoProjects($todoList = array())
|
||||
public function getTodoProjects(array $todoList = array()): array
|
||||
{
|
||||
$projectIdList = array();
|
||||
|
||||
foreach($todoList as $type => $todos)
|
||||
{
|
||||
$todoIdList = array_keys($todos);
|
||||
@@ -626,13 +586,8 @@ class todoModel extends model
|
||||
}
|
||||
|
||||
$todoIdList = array_unique($todoIdList);
|
||||
if($type == 'task') $projectIdList[$type] = $this->dao->select('id,project')->from(TABLE_TASK)->where('id')->in($todoIdList)->fetchPairs('id', 'project');
|
||||
if($type == 'bug') $projectIdList[$type] = $this->dao->select('id,project')->from(TABLE_BUG)->where('id')->in($todoIdList)->fetchPairs('id', 'project');
|
||||
if($type == 'issue') $projectIdList[$type] = $this->dao->select('id,project')->from(TABLE_ISSUE)->where('id')->in($todoIdList)->fetchPairs('id', 'project');
|
||||
if($type == 'risk') $projectIdList[$type] = $this->dao->select('id,project')->from(TABLE_RISK)->where('id')->in($todoIdList)->fetchPairs('id', 'project');
|
||||
if($type == 'opportunity') $projectIdList[$type] = $this->dao->select('id,project')->from(TABLE_OPPORTUNITY)->where('id')->in($todoIdList)->fetchPairs('id', 'project');
|
||||
if($type == 'review') $projectIdList[$type] = $this->dao->select('id,project')->from(TABLE_REVIEW)->where('id')->in($todoIdList)->fetchPairs('id', 'project');
|
||||
if($type == 'testtask') $projectIdList[$type] = $this->dao->select('id,project')->from(TABLE_TESTTASK)->where('id')->in($todoIdList)->fetchPairs('id', 'project');
|
||||
$typeTable = array('task' => TABLE_TASK,'bug' => TABLE_BUG,'issue' => TABLE_ISSUE,'risk' => TABLE_RISK,'opportunity' => TABLE_OPPORTUNITY,'review' => TABLE_REVIEW,'testtask' => TABLE_TESTTASK);
|
||||
$projectIdList[$type] = $this->dao->select('id,project')->from($typeTable[$type])->where('id')->in($todoIdList)->fetchPairs('id', 'project');
|
||||
}
|
||||
|
||||
return $projectIdList;
|
||||
@@ -680,4 +635,47 @@ class todoModel extends model
|
||||
{
|
||||
return $this->todoTao->updateDate($todoIDList, $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导出的待办数据。
|
||||
* Get data for export todo.
|
||||
*
|
||||
* @param string $orderBy
|
||||
* @param object $formData
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getByExportList(string $orderBy, object $formData): array
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_TODO)
|
||||
->where($this->session->todoReportCondition)
|
||||
->beginIF($formData->rawdata->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi()
|
||||
->orderBy($orderBy)->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据待办ID获取多条待办。
|
||||
* Get todo data by id list.
|
||||
*
|
||||
* @param array $todoIdList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTodosByIdList(array $todoIdList): array
|
||||
{
|
||||
return $this->todoTao->fetchRows($todoIdList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据待办ID更新待办数据。
|
||||
* Update todo data by id.
|
||||
*
|
||||
* @param array $todoIdList
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function updateTodoDataByID(int $todoID, object $todo): bool
|
||||
{
|
||||
return $this->todoTao->updateRow($todoID, $todo);
|
||||
}
|
||||
}
|
||||
|
||||
+39
-5
@@ -4,8 +4,8 @@ declare(strict_types=1);
|
||||
class todoTao extends todoModel
|
||||
{
|
||||
/**
|
||||
* 获取单条待办。
|
||||
* Get a todo.
|
||||
* 获取单条待办.
|
||||
*
|
||||
* @param int $todoID
|
||||
* @param object $todo
|
||||
@@ -16,6 +16,18 @@ class todoTao extends todoModel
|
||||
return $this->dao->select('*')->from(TABLE_TODO)->where('id')->eq($todoID)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取多条待办。
|
||||
* Get a todo.
|
||||
*
|
||||
* @param array $todoIdList
|
||||
* @return array
|
||||
*/
|
||||
protected function fetchRows(array $todoIdList): array
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_TODO)->where('id')->in(array_keys($todoIdList))->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入待办数据
|
||||
* Insert todo data.
|
||||
@@ -48,8 +60,8 @@ class todoTao extends todoModel
|
||||
{
|
||||
$this->dao->update(TABLE_TODO)->data($todo)
|
||||
->autoCheck()
|
||||
->checkIF(in_array($todo->type, array('custom', 'feedback')), $this->config->todo->edit->requiredFields, 'notempty')
|
||||
->checkIF(in_array($todo->type, $this->config->todo->moduleList) && $todo->objectID == 0, 'objectID', 'notempty')
|
||||
->checkIF(isset($todo->type) && in_array($todo->type, array('custom', 'feedback')), $this->config->todo->edit->requiredFields, 'notempty')
|
||||
->checkIF(isset($todo->type) && in_array($todo->type, $this->config->todo->moduleList) && $todo->objectID == 0, 'objectID', 'notempty')
|
||||
->where('id')->eq($todoID)
|
||||
->exec();
|
||||
|
||||
@@ -82,10 +94,11 @@ class todoTao extends todoModel
|
||||
* Process the data for the todo to be created.
|
||||
*
|
||||
* @param object $todoData
|
||||
* @param object $formData
|
||||
* @access protected
|
||||
* @return object|false
|
||||
*/
|
||||
protected function processCreateData(object $todoData): object|false
|
||||
protected function processCreateData(object $todoData, object $formData): object|false
|
||||
{
|
||||
if(!isset($todoData->pri) and in_array($todoData->type, $this->config->todo->moduleList) and !in_array($todoData->type, array('review', 'feedback')))
|
||||
{
|
||||
@@ -117,7 +130,7 @@ class todoTao extends todoModel
|
||||
}
|
||||
if(empty($todoData->cycle)) unset($todoData->config);
|
||||
|
||||
return $this->loadModel('file')->processImgURL($todoData, $this->config->todo->editor->create['id'], $this->post->uid);
|
||||
return $this->loadModel('file')->processImgURL($todoData, $this->config->todo->editor->create['id'], $formData->rawdata->uid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -323,4 +336,25 @@ class todoTao extends todoModel
|
||||
$this->dao->update(TABLE_TODO)->set('date')->eq($date)->where('id')->in($todoIdList)->exec();
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的待办事项数量。
|
||||
* Get todo count on the account.
|
||||
*
|
||||
* @param string $account
|
||||
* @access protected
|
||||
* @return int
|
||||
*/
|
||||
protected function getTodoCountByAccount(string $account): int
|
||||
{
|
||||
return $this->dao->select('count(*) as count')->from(TABLE_TODO)
|
||||
->where('cycle')->eq('0')
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->andWhere('account', true)->eq($account)
|
||||
->orWhere('assignedTo')->eq($account)
|
||||
->orWhere('finishedBy')->eq($account)
|
||||
->markRight(1)
|
||||
->fetch('count');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,20 +6,7 @@ su('admin');
|
||||
|
||||
function initData()
|
||||
{
|
||||
$project = zdTable('todo');
|
||||
$project->id->range('1-5');
|
||||
$project->account->range('admin');
|
||||
$project->date->prefix('2023-04-2')->range('1-9');
|
||||
$project->begin->range('1000-1100');
|
||||
$project->end->range('1200-1300');
|
||||
$project->type->range("custom");
|
||||
$project->cycle->range("0");
|
||||
$project->pri->range("3");
|
||||
$project->name->prefix('我的待办')->range("1-5");
|
||||
$project->desc->prefix('这是我的描述')->range("1-5");
|
||||
$project->status->range("wait");
|
||||
|
||||
$project->gen(5);
|
||||
zdTable('todo')->config('assignto')->gen(5);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,29 +15,29 @@ title=测试 todoModel->assignTo();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 执行todo模块的assignTo方法,参数是$todoIDList[0], $todo1
|
||||
- 指派todo 1给test1 选择待定
|
||||
- 属性assignedTo @test1
|
||||
- 属性date @20300101
|
||||
- 属性begin @1000
|
||||
- 属性end @1400
|
||||
|
||||
- 执行todo模块的assignTo方法,参数是$todoIDList[1], $todo2
|
||||
- 指派todo 2给test1 暂时不设定时间
|
||||
- 属性assignedTo @test1
|
||||
- 属性begin @2400
|
||||
- 属性end @2400
|
||||
|
||||
- 执行todo模块的assignTo方法,参数是$todoIDList[2], $todo3
|
||||
- 指派todo 3给test1
|
||||
- 属性assignedTo @test1
|
||||
- 属性begin @1002
|
||||
- 属性end @1402
|
||||
|
||||
- 执行todo模块的assignTo方法,参数是$todoIDList[3], $todo4
|
||||
- 指派todo 4给admin future=on 验证 date默认值
|
||||
- 属性assignedTo @admin
|
||||
- 属性date @20300101
|
||||
- 属性begin @1200
|
||||
- 属性end @1502
|
||||
|
||||
- 执行todo模块的assignTo方法,参数是$todoIDList[4], $todo5
|
||||
- 指派todo 5给admin future=on lblDisableDate=on 验证date,begin,end默认值
|
||||
- 属性assignedTo @admin
|
||||
- 属性date @20300101
|
||||
- 属性begin @2400
|
||||
@@ -62,7 +49,7 @@ cid=1
|
||||
|
||||
initData();
|
||||
|
||||
$todoIDList = array('1', '2', '3', '4', '5');
|
||||
$todoIDList = range(1,5);
|
||||
|
||||
$todo1 = new stdclass();
|
||||
$todo1->assignedTo = 'test1';
|
||||
|
||||
@@ -6,20 +6,7 @@ su('admin');
|
||||
|
||||
function initData()
|
||||
{
|
||||
$project = zdTable('todo');
|
||||
$project->id->range('1-100');
|
||||
$project->account->range('admin');
|
||||
$project->date->prefix('2023-04-2')->range('1-9');
|
||||
$project->begin->range('1000-1100');
|
||||
$project->end->range('1200-1300');
|
||||
$project->type->range("custom");
|
||||
$project->cycle->range("0");
|
||||
$project->pri->range("3");
|
||||
$project->name->prefix('我的待办')->range("1-5");
|
||||
$project->desc->prefix('这是我的描述')->range("1-5");
|
||||
$project->status->range("wait");
|
||||
|
||||
$project->gen(10);
|
||||
zdTable('todo')->config('batchfinish')->gen(10);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,21 +15,22 @@ title=测试批量完成待办 todoModel->batchFinish();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 执行todo模块的getById方法,参数是$todoIDList[0]属性status @done
|
||||
- 批量完成todo验证状态wait->done属性status @done
|
||||
|
||||
- 执行todo模块的getById方法,参数是$todoIDList[1]属性status @done
|
||||
- 批量完成todo验证状态donging->done属性status @done
|
||||
|
||||
- 执行todo模块的getById方法,参数是$todoIDList[2]属性status @done
|
||||
- 批量完成todo验证状态done属性status @done
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
$todoIDList = array('1', '2', '3');
|
||||
initData();
|
||||
$todoIDList = range(1,3);
|
||||
|
||||
$todo = new todoTest();
|
||||
$todo->batchFinishTest($todoIDList);
|
||||
|
||||
r($todo->getByIdTest($todoIDList[0])) && p('status') && e('done'); // 批量完成todo验证状态done
|
||||
r($todo->getByIdTest($todoIDList[1])) && p('status') && e('done'); // 批量完成todo验证状态done
|
||||
r($todo->getByIdTest($todoIDList[0])) && p('status') && e('done'); // 批量完成todo验证状态wait->done
|
||||
r($todo->getByIdTest($todoIDList[1])) && p('status') && e('done'); // 批量完成todo验证状态donging->done
|
||||
r($todo->getByIdTest($todoIDList[2])) && p('status') && e('done'); // 批量完成todo验证状态done
|
||||
@@ -16,13 +16,7 @@ pid=1
|
||||
global $tester;
|
||||
$tester->loadModel('todo');
|
||||
|
||||
$todo = zdTable('todo');
|
||||
$todo->id->range('1');
|
||||
$todo->name->prefix("待办")->range('1');
|
||||
$todo->date->range('`2023-04-23`');
|
||||
$todo->type->range('custom');
|
||||
$todo->status->range('wait');
|
||||
$todo->gen(1, '', true);
|
||||
zdTable('todo')->config('close')->gen(1);
|
||||
|
||||
r($tester->todo->getByID(1)) && p('status') && e('wait');
|
||||
r($tester->todo->close(1)) && p() && e(1);
|
||||
|
||||
@@ -6,20 +6,7 @@ su('admin');
|
||||
|
||||
function initData()
|
||||
{
|
||||
$project = zdTable('todo');
|
||||
$project->id->range('1-100');
|
||||
$project->account->range('admin');
|
||||
$project->date->prefix('2023-04-2')->range('1-9');
|
||||
$project->begin->range('1000-1100');
|
||||
$project->end->range('1200-1300');
|
||||
$project->type->range("custom");
|
||||
$project->cycle->range("0");
|
||||
$project->pri->range("3");
|
||||
$project->name->prefix('我的待办')->range("1-5");
|
||||
$project->desc->prefix('这是我的描述')->range("1-5");
|
||||
$project->status->range("wait");
|
||||
|
||||
$project->gen(10);
|
||||
zdTable('todo')->config('delete')->gen(10);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,11 +15,11 @@ title=测试删除todo todoModel->delete();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 执行todo模块的delete方法,参数是8, no
|
||||
- 删除指定id的待办,取消确认
|
||||
- 属性id @8
|
||||
- 属性deleted @0
|
||||
|
||||
- 执行todo模块的getById方法,参数是8属性deleted @1
|
||||
- 验证删除id不存在的todo信息属性deleted @1
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,20 +1,10 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
include dirname(__FILE__, 2) . '/todo.class.php';
|
||||
su('admin');
|
||||
|
||||
function initData()
|
||||
{
|
||||
$project = zdTable('todo');
|
||||
$project->id->range('1-5');
|
||||
$project->name->prefix("自定义的待办")->range('1-5');
|
||||
$project->type->range(1);
|
||||
$project->status->range("wait,doing,done,closed,closed");
|
||||
$project->gen(5);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
title=测试 todoModel->editDateTest();
|
||||
@@ -27,8 +17,7 @@ pid=1
|
||||
global $tester;
|
||||
$tester->loadModel('todo');
|
||||
|
||||
initData();
|
||||
zdTable('todo')->config('editdate')->gen(5);
|
||||
|
||||
r($tester->todo->editDate(array(1), '2023-06-07')) && p() && e(true); // 获取id为1的待办的日期
|
||||
r($tester->todo->editDate(array(2, 3), '2023-04-27')) && p() && e(true); // 获取id 为1,2待办的日期
|
||||
#r($tester->todo->editDate(array(9), '2023-04-17')) && p() && e('0'); // 修改不存在的待办的日期
|
||||
r($tester->todo->editDate(array(1), '2023-06-07')) && p() && e(true); // 修改id为1的待办的日期
|
||||
r($tester->todo->editDate(array(2, 3), '2023-04-27')) && p() && e(true); // 修改id为2,3的待办的日期
|
||||
|
||||
@@ -6,20 +6,7 @@ su('admin');
|
||||
|
||||
function initData()
|
||||
{
|
||||
$project = zdTable('todo');
|
||||
$project->id->range('1-100');
|
||||
$project->account->range('admin');
|
||||
$project->date->prefix('2023-04-2')->range('1-9');
|
||||
$project->begin->range('1000-1100');
|
||||
$project->end->range('1200-1300');
|
||||
$project->type->range("custom");
|
||||
$project->cycle->range("0");
|
||||
$project->pri->range("3");
|
||||
$project->name->prefix('我的待办')->range("1-5");
|
||||
$project->desc->prefix('这是我的描述')->range("1-5");
|
||||
$project->status->range("wait,doing,done");
|
||||
|
||||
$project->gen(10);
|
||||
zdTable('todo')->config('finish')->gen(10);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,11 +15,11 @@ title=测试完成待办 todoModel->finish();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 执行todo模块的finish方法,参数是$todoIDList[0]属性status @done
|
||||
- 结束一个状态为wait的todo属性status @done
|
||||
|
||||
- 执行todo模块的finish方法,参数是$todoIDList[1]属性status @done
|
||||
- 结束一个状态为doing的todo属性status @done
|
||||
|
||||
- 执行todo模块的finish方法,参数是$todoIDList[2]属性status @done
|
||||
- 结束一个状态为done的todo属性status @done
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
include dirname(__FILE__, 2) . '/todo.class.php';
|
||||
su('admin');
|
||||
|
||||
function initData()
|
||||
function initData ()
|
||||
{
|
||||
$project = zdTable('todo');
|
||||
$project->id->range('1-5');
|
||||
$project->name->prefix("自定义的待办")->range('1-5');
|
||||
$project->type->range(1);
|
||||
$project->status->range("wait,doing,done,closed,closed");
|
||||
$project->gen(5);
|
||||
zdTable('todo')->config('getbyid')->gen(5);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
title=测试 todoModel->getById();
|
||||
title=测试 todoModel->getByID();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
@@ -29,7 +25,6 @@ $todo = new todoTest();
|
||||
|
||||
initData();
|
||||
|
||||
r($todo->getByIdTest($todoIDList[0])) && p('name,status') && e('自定义的待办1,wait'); // 获取id为1的todo信息
|
||||
r($todo->getByIdTest($todoIDList[1])) && p('name,status') && e('自定义的待办2,doing'); // 获取id为2的todo信息
|
||||
r($todo->getByIdTest($todoIDList[3])) && p('name,status') && e('自定义的待办5,closed'); // 获取id为5的todo信息
|
||||
r($todo->getByIdTest($todoIDList[4])) && p() && e('0'); // 获取id不存在的todo信息
|
||||
r($todo->getByIDTest($todoIDList[0])) && p('name,status') && e('自定义的待办1,wait'); // 获取id为1的todo信息
|
||||
r($todo->getByIDTest($todoIDList[1])) && p('name,status') && e('自定义的待办2,doing'); // 获取id为2的todo信息
|
||||
r($todo->getByIDTest($todoIDList[3])) && p('name,status') && e('自定义的待办5,closed'); // 获取id为5的todo信息
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
title: zt_assignto
|
||||
author: liuchenglong
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-5
|
||||
- field: account
|
||||
range: 'admin'
|
||||
- field: date
|
||||
range: 1-9
|
||||
prefix: '2023-04-2'
|
||||
- field: begin
|
||||
range: 1000-1100
|
||||
- field: end
|
||||
range: 1200-1300
|
||||
- field: type
|
||||
range: 'custom'
|
||||
- field: cycle
|
||||
range: 0
|
||||
- field: pri
|
||||
range: 3
|
||||
- field: name
|
||||
range: 1-5
|
||||
prefix: '我的待办'
|
||||
- field: desc
|
||||
range: 1-5
|
||||
prefix: '这是待办描述'
|
||||
- field: status
|
||||
range: 'wait'
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
title: zt_batchfinish
|
||||
author: liuchenglong
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-100
|
||||
- field: account
|
||||
range: 'admin'
|
||||
- field: date
|
||||
range: 1-9
|
||||
prefix: '2023-04-2'
|
||||
- field: begin
|
||||
range: 1000-1100
|
||||
- field: end
|
||||
range: 1200-1300
|
||||
- field: type
|
||||
range: 'custom'
|
||||
- field: cycle
|
||||
range: 0
|
||||
- field: pri
|
||||
range: 3
|
||||
- field: name
|
||||
range: 1-5
|
||||
prefix: '我的待办'
|
||||
- field: desc
|
||||
range: 1-5
|
||||
prefix: '这是待办描述'
|
||||
- field: status
|
||||
range: 'wait,doing,done'
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
title: Create todos for todoModel::close UTC.
|
||||
desc: Create todos for todoModel::close UTC.
|
||||
version: 1.0.0
|
||||
|
||||
fields:
|
||||
- field: id
|
||||
range: 1
|
||||
- field: date
|
||||
range: '`2023-04-23`'
|
||||
- field: type
|
||||
range: custom
|
||||
- field: status
|
||||
range: wait
|
||||
- field: id
|
||||
range: 1
|
||||
@@ -0,0 +1,32 @@
|
||||
title: zt_delete
|
||||
author: liuchenglong
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-100
|
||||
- field: account
|
||||
range: 'admin'
|
||||
- field: date
|
||||
range: 1-9
|
||||
prefix: '2023-04-2'
|
||||
- field: begin
|
||||
range: 1000-1100
|
||||
- field: end
|
||||
range: 1200-1300
|
||||
- field: type
|
||||
range: 'custom'
|
||||
- field: cycle
|
||||
range: 0
|
||||
- field: pri
|
||||
range: 3
|
||||
- field: name
|
||||
range: 1-5
|
||||
prefix: '我的待办'
|
||||
- field: desc
|
||||
range: 1-5
|
||||
prefix: '这是待办描述'
|
||||
- field: status
|
||||
range: 'wait,doing,done'
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
title: Create todos for todoModel::close UTC.
|
||||
desc: Create todos for todoModel::close UTC.
|
||||
version: 1.0.0
|
||||
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-5
|
||||
- field: date
|
||||
range: '`2023-05-03`'
|
||||
- field: type
|
||||
range: custom
|
||||
- field: status
|
||||
range: wait
|
||||
@@ -0,0 +1,32 @@
|
||||
title: zt_finish
|
||||
author: liuchenglong
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-100
|
||||
- field: account
|
||||
range: 'admin'
|
||||
- field: date
|
||||
range: 1-9
|
||||
prefix: '2023-04-2'
|
||||
- field: begin
|
||||
range: 1000-1100
|
||||
- field: end
|
||||
range: 1200-1300
|
||||
- field: type
|
||||
range: 'custom'
|
||||
- field: cycle
|
||||
range: 0
|
||||
- field: pri
|
||||
range: 3
|
||||
- field: name
|
||||
range: 1-5
|
||||
prefix: '我的待办'
|
||||
- field: desc
|
||||
range: 1-5
|
||||
prefix: '这是待办描述'
|
||||
- field: status
|
||||
range: 'wait,doing,done'
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
title: zt_getbyid
|
||||
author: jukui
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-5
|
||||
- field: account
|
||||
range: 'admin'
|
||||
- field: date
|
||||
range: 1-9
|
||||
prefix: '2023-04-2'
|
||||
- field: begin
|
||||
range: 1000-1100
|
||||
- field: end
|
||||
range: 1200-1300
|
||||
- field: type
|
||||
range: 'custom'
|
||||
- field: cycle
|
||||
range: 0
|
||||
- field: pri
|
||||
range: 3
|
||||
- field: name
|
||||
range: 1-5
|
||||
prefix: '自定义的待办'
|
||||
- field: desc
|
||||
range: 1-5
|
||||
prefix: '这是待办描述'
|
||||
- field: status
|
||||
range: 'wait,doing,done,closed,closed'
|
||||
|
||||
|
||||
+274
-75
@@ -11,7 +11,7 @@ class todoZen extends todo
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function buildCreateView(string $date): void
|
||||
protected function buildCreateView(string $date)
|
||||
{
|
||||
$this->view->title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->create;
|
||||
$this->view->date = date('Y-m-d', strtotime($date));
|
||||
@@ -41,6 +41,26 @@ class todoZen extends todo
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成指派待办视图数据。
|
||||
* Build assignTo form data.
|
||||
*
|
||||
* @param int $todoID
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function buildAssignToView(int $todoID): void
|
||||
{
|
||||
$this->view->todo = $this->todo->getByID($todoID);
|
||||
$this->view->members = $this->loadModel('user')->getPairs('noclosed|noempty|nodeleted');
|
||||
$this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
|
||||
$this->view->actions = $this->loadModel('action')->getList('todo', $todoID);
|
||||
$this->view->users = $this->user->getPairs('noletter');
|
||||
$this->view->time = date::now();
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理请求数据
|
||||
* Processing request data.
|
||||
@@ -51,11 +71,12 @@ class todoZen extends todo
|
||||
*/
|
||||
protected function beforeCreate(object $formData): object
|
||||
{
|
||||
$objectType = $this->post->type;
|
||||
$rowData = $formData->rawdata;
|
||||
$objectType = $rowData->type;
|
||||
$hasObject = in_array($objectType, $this->config->todo->moduleList);
|
||||
|
||||
$objectID = 0;
|
||||
if($hasObject && $objectType) $objectID = $this->post->uid ? $this->post->$objectType : $this->post->objectID;
|
||||
if($hasObject && $objectType) $objectID = $rowData->uid ? $rowData->$objectType : $rowData->objectID;
|
||||
|
||||
$data = $formData->add('account', $this->app->user->account)
|
||||
->setDefault('objectID', 0)
|
||||
@@ -65,11 +86,11 @@ class todoZen extends todo
|
||||
->setDefault('assignedDate', helper::now())
|
||||
->cleanInt('pri, begin, end, private')
|
||||
->setIF($hasObject && $objectType, 'objectID', $objectID)
|
||||
->setIF($this->post->date == false, 'date', '2030-01-01')
|
||||
->setIF($this->post->begin == false, 'begin', '2400')
|
||||
->setIF($this->post->begin == false or $this->post->end == false, 'end', '2400')
|
||||
->setIF($this->post->status == 'done', 'finishedBy', $this->app->user->account)
|
||||
->setIF($this->post->status == 'done', 'finishedDate', helper::now())
|
||||
->setIF($rowData->date == false, 'date', '2030-01-01')
|
||||
->setIF($rowData->begin == false, 'begin', '2400')
|
||||
->setIF($rowData->begin == false or $rowData->end == false, 'end', '2400')
|
||||
->setIF($rowData->status == 'done', 'finishedBy', $this->app->user->account)
|
||||
->setIF($rowData->status == 'done', 'finishedDate', helper::now())
|
||||
->stripTags($this->config->todo->editor->create['id'], $this->config->allowedTags)
|
||||
->remove(implode(',', $this->config->todo->moduleList) . ',uid')
|
||||
->get();
|
||||
@@ -82,12 +103,13 @@ class todoZen extends todo
|
||||
* Create a todo after data processing.
|
||||
*
|
||||
* @param object $todo
|
||||
* @param object $formData
|
||||
* @access protected
|
||||
* @return object
|
||||
*/
|
||||
protected function afterCreate(object $todo): object
|
||||
protected function afterCreate(object $todo, object $formData): object
|
||||
{
|
||||
$this->loadModel('file')->updateObjectID($this->post->uid, $todo->id, 'todo');
|
||||
$this->loadModel('file')->updateObjectID($formData->rawdata->uid, $todo->id, 'todo');
|
||||
|
||||
$this->loadModel('score')->create('todo', 'create', $todo->id);
|
||||
|
||||
@@ -156,7 +178,7 @@ class todoZen extends todo
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑完成待办后数据处理
|
||||
* 编辑完成待办后数据处理。
|
||||
* Handle data after edit todo.
|
||||
*
|
||||
* @param object $todo
|
||||
@@ -171,89 +193,180 @@ class todoZen extends todo
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
protected function batchEditFromMyTodo($type, $userID, $status)
|
||||
/**
|
||||
* 批量编辑页面渲染。
|
||||
* Batch edit view display.
|
||||
*
|
||||
* @param object $formData
|
||||
* @param string $type
|
||||
* @param int $userID
|
||||
* @param string $status
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function batchEditFromMyTodo(object $formData, string $type, int $userID, string $status): void
|
||||
{
|
||||
/* Initialize vars. */
|
||||
$editedTodos = array();
|
||||
$todoIDList = array();
|
||||
$reviews = array();
|
||||
$columns = 7;
|
||||
$editedTodos = $objectIdList = $reviews = array();
|
||||
$columns = 7;
|
||||
unset($this->lang->todo->typeList['cycle']);
|
||||
|
||||
if($userID == '') $userID = $this->app->user->id;
|
||||
if(empty($userID)) $userID = $this->app->user->id;
|
||||
$user = $this->loadModel('user')->getById($userID, 'id');
|
||||
$account = $user->account;
|
||||
|
||||
if($this->config->edition == 'max') $reviews = $this->loadModel('review')->getUserReviewPairs($account);
|
||||
$allTodos = $this->todo->getList($type, $account, $status);
|
||||
if($this->post->todoIDList) $todoIDList = $this->post->todoIDList;
|
||||
list($editedTodos, $objectIdList) = $this->getBatchEditInitTodos($formData, $type, $account, $status);
|
||||
|
||||
/* Initialize todos whose need to edited. */
|
||||
foreach($allTodos as $todo)
|
||||
{
|
||||
if(in_array($todo->id, $todoIDList))
|
||||
{
|
||||
$editedTodos[$todo->id] = $todo;
|
||||
if($todo->type != 'custom')
|
||||
{
|
||||
if(!isset($objectIDList[$todo->type])) $objectIDList[$todo->type] = array();
|
||||
$objectIDList[$todo->type][$todo->objectID] = $todo->objectID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$bugs = $this->bug->getUserBugPairs($account, true, 0, '', '', isset($objectIDList['bug']) ? $objectIDList['bug'] : '');
|
||||
$tasks = $this->task->getUserTaskPairs($account, 'wait,doing', '', isset($objectIDList['task']) ? $objectIDList['task'] : '');
|
||||
$storys = $this->loadModel('story')->getUserStoryPairs($account, 10, 'story', '', isset($objectIDList['story']) ? $objectIDList['story'] : '');
|
||||
if($this->config->edition != 'open') $this->view->feedbacks = $this->loadModel('feedback')->getUserFeedbackPairs($account, '', isset($objectIDList['feedback']) ? $objectIDList['feedback'] : '');
|
||||
$bugs = $this->bug->getUserBugPairs($account, true, 0, '', '', isset($objectIdList['bug']) ? $objectIdList['bug'] : '');
|
||||
$tasks = $this->task->getUserTaskPairs($account, 'wait,doing', '', isset($objectIdList['task']) ? $objectIdList['task'] : '');
|
||||
$storys = $this->loadModel('story')->getUserStoryPairs($account, 10, 'story', '', isset($objectIdList['story']) ? $objectIdList['story'] : '');
|
||||
$users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noempty');
|
||||
$testtasks = $this->loadModel('testtask')->getUserTestTaskPairs($account);
|
||||
if($this->config->edition == 'biz' || $this->config->edition == 'max') $feedbacks = $this->loadModel('feedback')->getUserFeedbackPairs($account, '', isset($objectIdList['feedback']) ? $objectIdList['feedback'] : '');
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
$issues = $this->loadModel('issue')->getUserIssuePairs($account);
|
||||
$risks = $this->loadmodel('risk')->getUserRiskPairs($account);
|
||||
$opportunities = $this->loadmodel('opportunity')->getUserOpportunityPairs($account);
|
||||
$reviews = $this->loadModel('review')->getUserReviewPairs($account);
|
||||
}
|
||||
$testtasks = $this->loadModel('testtask')->getUserTestTaskPairs($account);
|
||||
|
||||
/* Judge whether the edited todos is too large. */
|
||||
$countInputVars = count($editedTodos) * $columns;
|
||||
$showSuhosinInfo = common::judgeSuhosinSetting($countInputVars);
|
||||
|
||||
unset($this->lang->todo->typeList['cycle']);
|
||||
/* Set Custom*/
|
||||
foreach(explode(',', $this->config->todo->list->customBatchEditFields) as $field) $customFields[$field] = $this->lang->todo->$field;
|
||||
$this->view->customFields = $customFields;
|
||||
$this->view->showFields = $this->config->todo->custom->batchEditFields;
|
||||
|
||||
/* Assign. */
|
||||
$title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->batchEdit;
|
||||
$position[] = html::a($this->createLink('my', 'todo'), $this->lang->my->todo);
|
||||
$position[] = $this->lang->todo->common;
|
||||
$position[] = $this->lang->todo->batchEdit;
|
||||
|
||||
if($showSuhosinInfo) $this->view->suhosinInfo = extension_loaded('suhosin') ? sprintf($this->lang->suhosinInfo, $countInputVars) : sprintf($this->lang->maxVarsInfo, $countInputVars);
|
||||
$this->view->bugs = $bugs;
|
||||
$this->view->tasks = $tasks;
|
||||
$this->view->storys = $storys;
|
||||
$this->view->bugs = $bugs;
|
||||
$this->view->tasks = $tasks;
|
||||
$this->view->storys = $storys;
|
||||
$this->view->reviews = $reviews;
|
||||
$this->view->testtasks = $testtasks;
|
||||
$this->view->editedTodos = $editedTodos;
|
||||
$this->view->users = $users;
|
||||
if($this->config->edition == 'biz' || $this->config->edition == 'max') $this->view->feedback = $feedbacks;
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
$this->view->issues = $issues;
|
||||
$this->view->risks = $risks;
|
||||
$this->view->opportunities = $opportunities;
|
||||
}
|
||||
$this->view->reviews = $reviews;
|
||||
$this->view->testtasks = $testtasks;
|
||||
$this->view->editedTodos = $editedTodos;
|
||||
$this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
|
||||
$this->view->time = date::now();
|
||||
$this->view->title = $title;
|
||||
$this->view->position = $position;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noempty');
|
||||
|
||||
$this->buildBatchEditView();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取批量编辑页面初始化待办数据。
|
||||
* Get batch edit page initialization todo data.
|
||||
*
|
||||
* @param object $formData
|
||||
* @param string $type
|
||||
* @param string $account
|
||||
* @param string $status
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
private function getBatchEditInitTodos(object $formData, string $type, string $account, string $status): array
|
||||
{
|
||||
$editedTodos = array();
|
||||
$objectIdList = array();
|
||||
$todoIdList = array();
|
||||
|
||||
$allTodos = $this->todo->getList($type, $account, $status);
|
||||
if($formData->data->todoIDList) $todoIdList = $formData->data->todoIDList;
|
||||
|
||||
/* Initialize todos whose need to edited. */
|
||||
foreach($allTodos as $todo)
|
||||
{
|
||||
if(in_array($todo->id, $todoIdList))
|
||||
{
|
||||
$editedTodos[$todo->id] = $todo;
|
||||
if($todo->type != 'custom')
|
||||
{
|
||||
if(!isset($objectIdList[$todo->type])) $objectIdList[$todo->type] = array();
|
||||
$objectIdList[$todo->type][$todo->objectID] = $todo->objectID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array($editedTodos, $objectIdList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成批量创建待办视图数据。
|
||||
* Build batch edit view.
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function buildBatchEditView(): void
|
||||
{
|
||||
/* Set Custom*/
|
||||
foreach(explode(',', $this->config->todo->list->customBatchEditFields) as $field) $customFields[$field] = $this->lang->todo->$field;
|
||||
$this->view->customFields = $customFields;
|
||||
$this->view->showFields = $this->config->todo->custom->batchEditFields;
|
||||
$this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
|
||||
$this->view->time = date::now();
|
||||
$this->view->title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->batchEdit;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
protected function batchEditFromTodoBatchEdit($formData)
|
||||
/**
|
||||
* 处理批量编辑待办数据。
|
||||
* Build batch edit view.
|
||||
*
|
||||
* @param object $formData
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function beforeBatchEdit(object $formData): array
|
||||
{
|
||||
$todos = array();
|
||||
$data = $formData->rawdata;
|
||||
$todoIdList = $formData->data->todoIDList ? $formData->data->todoIDList : array();
|
||||
|
||||
if(!empty($todoIdList))
|
||||
{
|
||||
/* Initialize todos from the post data. */
|
||||
$oldTodos = $this->todo->getTodosByIdList($todoIdList);
|
||||
foreach($todoIdList as $todoID)
|
||||
{
|
||||
$oldTodo = $oldTodos[$todoID];
|
||||
|
||||
$todo = new stdclass();
|
||||
$todo->date = $data->dates[$todoID];
|
||||
$todo->type = $data->types[$todoID];
|
||||
$todo->pri = $data->pris[$todoID];
|
||||
$todo->status = $data->status[$todoID];
|
||||
$todo->name = !in_array($todo->type, $this->config->todo->moduleList) ? $data->names[$todoID] : '';
|
||||
$todo->begin = isset($data->begins[$todoID]) ? $data->begins[$todoID] : 2400;
|
||||
$todo->end = isset($data->ends[$todoID]) ? $data->ends[$todoID] : 2400;
|
||||
$todo->assignedTo = isset($data->assignedTos[$todoID]) ? $data->assignedTos[$todoID] : $oldTodo->assignedTo;
|
||||
|
||||
if(in_array($todo->type, $this->config->todo->moduleList))
|
||||
{
|
||||
$todo->objectID = isset($data->{$this->config->todo->objectList[$todo->type]}[$todoID]) ? $data->{$this->config->todo->objectList[$todo->type]}[$todoID] : 0;
|
||||
}
|
||||
if($todo->end < $todo->begin) return print(js::alert(sprintf($this->lang->error->gt, $this->lang->todo->end, $this->lang->todo->begin)));
|
||||
|
||||
$todos[$todoID] = $todo;
|
||||
}
|
||||
}
|
||||
|
||||
return $todos;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量编辑完成待办后数据处理。
|
||||
* After Batch edit todo data.
|
||||
*
|
||||
* @param array $allChanges
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function afterBatchEdit(array $allChanges): void
|
||||
{
|
||||
$allChanges = $this->todo->batchUpdate();
|
||||
foreach($allChanges as $todoID => $changes)
|
||||
{
|
||||
if(empty($changes)) continue;
|
||||
@@ -261,8 +374,6 @@ class todoZen extends todo
|
||||
$actionID = $this->loadModel('action')->create('todo', $todoID, 'edited');
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
return print(js::locate($this->session->todoList, 'parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -412,7 +523,7 @@ class todoZen extends todo
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理指派待办请求数据.
|
||||
* 处理指派待办请求数据。
|
||||
* Process assign todo request data.
|
||||
*
|
||||
* @param object $formData
|
||||
@@ -434,7 +545,7 @@ class todoZen extends todo
|
||||
}
|
||||
|
||||
/**
|
||||
* 指派待办.
|
||||
* 指派待办。
|
||||
* Assign a todo.
|
||||
*
|
||||
* @param object $todo
|
||||
@@ -446,16 +557,47 @@ class todoZen extends todo
|
||||
return $this->todo->assignTo($todo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取导出待办的字段。
|
||||
* 获取用户信息。
|
||||
* Get user info.
|
||||
*
|
||||
* @param array $fields
|
||||
* @param array $todoLang
|
||||
* @param int $userID
|
||||
* @access protected
|
||||
* @return object|false
|
||||
*/
|
||||
protected function getUserById(int $userID): object|false
|
||||
{
|
||||
return $this->loadModel('user')->getById($userID, 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录当前页面uri参数链接。
|
||||
* Set uri to session.
|
||||
*
|
||||
* @param string $uri
|
||||
* @access protected
|
||||
* @return true
|
||||
*/
|
||||
protected function setSessionUri(string $uri): bool
|
||||
{
|
||||
foreach($this->config->todo->sessionUri as $key => $value) $this->session->set($key, $uri, $value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取导出待办的字段和字段。
|
||||
* Get fields and info for export todo.
|
||||
*
|
||||
* @param array $todos
|
||||
* @param string $fields
|
||||
* @param array $todoLang
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function exportFields(array $fields, object $todoLang): array
|
||||
protected function exportTodoInfo(array $todos, string $fields, object $todoLang): array
|
||||
{
|
||||
$fields = explode(',', $fields);
|
||||
foreach($fields as $key => $fieldName)
|
||||
{
|
||||
$fieldName = trim($fieldName);
|
||||
@@ -463,10 +605,21 @@ class todoZen extends todo
|
||||
unset($fields[$key]);
|
||||
}
|
||||
unset($fields['objectID'], $fields['private']);
|
||||
return $fields;
|
||||
|
||||
if($this->config->edition != 'open') list($fields, $todos) = $this->loadModel('workflowfield')->appendDataFromFlow($fields, $todos);
|
||||
return array($todos, $fields);
|
||||
}
|
||||
|
||||
public function exportInfo($type, $account)
|
||||
/**
|
||||
* 获取待办关联的信息。
|
||||
* Get associated info for export todo.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $account
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function exportAssociated(string $type, string $account): array
|
||||
{
|
||||
if($type == 'max')
|
||||
{
|
||||
@@ -476,7 +629,7 @@ class todoZen extends todo
|
||||
$this->loadModel('opportunity')->getUserOpportunityPairs($account),
|
||||
);
|
||||
}
|
||||
else if($type == 'qcVersion')
|
||||
elseif($type == 'qcVersion')
|
||||
{
|
||||
return $this->loadModel('review')->getUserReviewPairs($account, 0, 'wait');
|
||||
}
|
||||
@@ -491,4 +644,50 @@ class todoZen extends todo
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理导出数据。
|
||||
* Deal with export data.
|
||||
*
|
||||
* @param array $todos
|
||||
* @param object $assemble
|
||||
* @param object $todoLang
|
||||
* @param array $times
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function assembleExportData(array $todos, object $assemble, object $todoLang, array $times): array
|
||||
{
|
||||
foreach($todos as $todo)
|
||||
{
|
||||
/* fill some field with useful value. */
|
||||
$todo->begin = $todo->begin == '2400' ? '' : (isset($times[$todo->begin]) ? $times[$todo->begin] : $todo->begin);
|
||||
$todo->end = $todo->end == '2400' ? '' : (isset($times[$todo->end]) ? $times[$todo->end] : $todo->end);
|
||||
|
||||
$type = $todo->type;
|
||||
if(isset($assemble->users[$todo->account])) $todo->account = $assemble->users[$todo->account];
|
||||
|
||||
if($type == 'bug') $todo->name = isset($assemble->bugs[$todo->objectID]) ? $assemble->bugs[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
if($type == 'task') $todo->name = isset($assemble->tasks[$todo->objectID]) ? $assemble->tasks[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
if($type == 'story') $todo->name = isset($assemble->stories[$todo->objectID]) ? $assemble->stories[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
if($type == 'testtask') $todo->name = isset($assemble->testTasks[$todo->objectID]) ? $assemble->testTasks[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
if($type == 'issue') $todo->name = isset($assemble->issues[$todo->objectID]) ? $assemble->issues[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
if($type == 'risk') $todo->name = isset($assemble->risks[$todo->objectID]) ? $assemble->risks[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
if($type == 'opportunity') $todo->name = isset($assemble->opportunities[$todo->objectID]) ? $assemble->opportunities[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
}
|
||||
if($type == 'review' && isset($this->config->qcVersion)) $todo->name = isset($assemble->reviews[$todo->objectID]) ? $assemble->reviews[$todo->objectID] . "(#$todo->objectID)" : '';
|
||||
|
||||
if(isset($todoLang->typeList[$type])) $todo->type = $todoLang->typeList[$type];
|
||||
if(isset($todoLang->priList[$todo->pri])) $todo->pri = $todoLang->priList[$todo->pri];
|
||||
if(isset($todoLang->statusList[$todo->status])) $todo->status = $todoLang->statusList[$todo->status];
|
||||
if($todo->private == 1) $todo->desc = $this->lang->todo->thisIsPrivate;
|
||||
|
||||
/* drop some field that is not needed. */
|
||||
unset($todo->objectID, $todo->private);
|
||||
}
|
||||
return $todos;
|
||||
}
|
||||
}
|
||||
|
||||
+17
-16
@@ -1,6 +1,7 @@
|
||||
title: zt_bug
|
||||
desc: Bug表
|
||||
version: 1.0
|
||||
desc: "Bug表"
|
||||
author: automated export
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-10000
|
||||
@@ -33,29 +34,29 @@ fields:
|
||||
- field: title2
|
||||
range: 1-10000
|
||||
- field: keywords
|
||||
range: []
|
||||
range: "[]"
|
||||
- field: severity
|
||||
range: 1-4
|
||||
- field: pri
|
||||
range: 1-4
|
||||
- field: type
|
||||
range: [codeerror,config,install,security,performance,standard,automation,designdefect,others]
|
||||
range: "[codeerror,config,install,security,performance,standard,automation,designdefect,others]"
|
||||
- field: os
|
||||
range: []{2},[win10,windows,android,ios]
|
||||
range: "[]{2},[win10,windows,android,ios]"
|
||||
- field: browser
|
||||
range: []
|
||||
range: "[]"
|
||||
- field: hardware
|
||||
range: []
|
||||
range: "[]"
|
||||
- field: found
|
||||
range: []
|
||||
range: "[]"
|
||||
- field: steps
|
||||
range: [<p>【步骤】</p><br/><p>【结果】</p><br/><p>【期望】</p><br/>,【步骤】进入成果展示<br/>【结果】乱码<br/>【期望】正常显示<br/>]
|
||||
range: "[<p>【步骤】</p><br/><p>【结果】</p><br/><p>【期望】</p><br/>,【步骤】进入成果展示<br/>【结果】乱码<br/>【期望】正常显示<br/>]"
|
||||
- field: status
|
||||
range: active{50},resolved{30},closed{20}
|
||||
- field: subStatus
|
||||
range: []
|
||||
range: "[]"
|
||||
- field: color
|
||||
range: [#3da7f5,#75c941,#2dbdb2,#797ec9,#ffaf38,#ff4e3e]
|
||||
range: "[#3da7f5,#75c941,#2dbdb2,#797ec9,#ffaf38,#ff4e3e]"
|
||||
- field: confirmed
|
||||
range: 0,1
|
||||
- field: activatedCount
|
||||
@@ -71,7 +72,7 @@ fields:
|
||||
- field: openedBuild
|
||||
range: 1,0,1,trunk{97}
|
||||
- field: assignedTo
|
||||
range: [admin,dev1,test1]{30},[]{20},[admin,dev1,test1]{20},[]{10},closed{20}
|
||||
range: "[admin,dev1,test1]{30},[]{20},[admin,dev1,test1]{20},[]{10},closed{20}"
|
||||
- field: assignedDate
|
||||
range: "(-1M)-(+1w):-1D"
|
||||
type: timestamp
|
||||
@@ -84,11 +85,11 @@ fields:
|
||||
loop: 0
|
||||
format: "YYYY-MM-DD"
|
||||
- field: resolvedBy
|
||||
range: []{50},$assignedTo{30},admin{20}
|
||||
range: "[]{50},$assignedTo{30},admin{20}"
|
||||
- field: resolution
|
||||
range: []{50},bydesign{5},duplicate{5},external{5},fixed{5},notrepro{2},postponed{3},willnotfix{5},fixed{10},bydesign,external,notrepro,postponed,willnotfix,duplicate{5}
|
||||
range: "[]{50},bydesign{5},duplicate{5},external{5},fixed{5},notrepro{2},postponed{3},willnotfix{5},fixed{10},bydesign,external,notrepro,postponed,willnotfix,duplicate{5}"
|
||||
- field: resolvedBuild
|
||||
range: []{55},trunk{15},[]{25},trunk{5}
|
||||
range: "[]{55},trunk{15},[]{25},trunk{5}"
|
||||
- field: resolvedDate
|
||||
range: "(+1w)-(-2w):-1D"
|
||||
type: timestamp
|
||||
@@ -97,7 +98,7 @@ fields:
|
||||
loop: 0
|
||||
format: "YYYY-MM-DD"
|
||||
- field: closedBy
|
||||
range: []{50},admin{30}
|
||||
range: "[]{50},admin{30}"
|
||||
- field: closedDate
|
||||
range:
|
||||
- field: duplicateBug
|
||||
|
||||
+5
-4
@@ -65,8 +65,11 @@ fields:
|
||||
range: ""
|
||||
- field: scriptedDate
|
||||
note: "脚本创建日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateB
|
||||
range: "(M)-(w)"
|
||||
type: timestamp
|
||||
prefix: "DateTime"
|
||||
postfix: ""
|
||||
format: "YY/MM/DD"
|
||||
- field: scriptStatus
|
||||
note: "脚本状态"
|
||||
range: ""
|
||||
@@ -81,8 +84,6 @@ fields:
|
||||
range: ""
|
||||
- field: color
|
||||
note: "标题颜色"
|
||||
from: common.color.v1.yaml
|
||||
use: color
|
||||
- field: frequency
|
||||
note: "使用频率"
|
||||
range: 1-3
|
||||
|
||||
+5
-10
@@ -59,40 +59,35 @@ fields:
|
||||
format: "YYYY-MM-DD hh:mm:ss"
|
||||
- field: editedBy
|
||||
note: "由谁编辑"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: editedDate
|
||||
note: "编辑者"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: assignedTo
|
||||
note: "指派给"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: assignedBy
|
||||
note: "由谁指派"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: assignedDate
|
||||
note: "指派日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
|
||||
+3
-4
@@ -147,12 +147,11 @@ fields:
|
||||
format: ""
|
||||
- field: editedDate
|
||||
note: "编辑日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
range: Y-m-d
|
||||
prefix: ""
|
||||
type: timestamp
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
format: "YYYY-MM-DD"
|
||||
- field: acl
|
||||
note: "权限"
|
||||
range: open,custom,private
|
||||
|
||||
@@ -83,20 +83,14 @@ fields:
|
||||
format: ""
|
||||
- field: editedBy
|
||||
note: "编辑者"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: editedDate
|
||||
note: "编辑日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
range: ""
|
||||
- field: deleted
|
||||
note: "是否删除"
|
||||
range: 0
|
||||
|
||||
+7
-12
@@ -12,16 +12,12 @@ fields:
|
||||
format: ""
|
||||
- field: pathname
|
||||
note: "路径名称"
|
||||
from: common.file.v1.yaml
|
||||
use: pathname
|
||||
loop: 0
|
||||
format: ""
|
||||
range: ""
|
||||
- field: title
|
||||
note: "文件标题"
|
||||
from: common.file.v1.yaml
|
||||
use: title
|
||||
range: 1-1000000
|
||||
prefix: "文件标题"
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: extension
|
||||
note: "文件后缀"
|
||||
@@ -60,12 +56,11 @@ fields:
|
||||
format: ""
|
||||
- field: addedDate
|
||||
note: "添加时间"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
range: "(M)-(w)"
|
||||
type: timestamp
|
||||
prefix: "DateTime"
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
format: "YY/MM/DD"
|
||||
- field: downloads
|
||||
note: "下载次数"
|
||||
range: "0-100"
|
||||
|
||||
+8
-13
@@ -105,40 +105,35 @@ fields:
|
||||
format: ""
|
||||
- field: createdBy
|
||||
note: "创建者"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: admin
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: createdDate
|
||||
note: "创建日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
range: "(M)-(w)"
|
||||
type: timestamp
|
||||
prefix: "DateTime"
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
format: "YY/MM/DD"
|
||||
- field: editedBy
|
||||
note: "编辑者"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: editedDate
|
||||
note: "编辑日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: lastExec
|
||||
note: "最后执行时间"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
|
||||
+16
-37
@@ -114,31 +114,28 @@ fields:
|
||||
format: ""
|
||||
- field: color
|
||||
note: "标题颜色"
|
||||
from: common.color.v1.yaml
|
||||
use: color
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: stage
|
||||
note: "所处阶段"
|
||||
range: [],wait,[],planned,[],projected,[],developing,[],developed,[],testing,[],tested,[],verified,[],released,[],closed
|
||||
range: "[],wait,[],planned,[],projected,[],developing,[],developed,[],testing,[],tested,[],verified,[],released,[],closed"
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: stagedBy
|
||||
note: "设置阶段者"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: mailto
|
||||
note: "抄送给"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
@@ -156,12 +153,11 @@ fields:
|
||||
format: ""
|
||||
- field: openedDate
|
||||
note: "创建日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
range: "(M)-(w)"
|
||||
type: timestamp
|
||||
prefix: "DateTime"
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
format: "YY/MM/DD"
|
||||
- field: assignedTo
|
||||
note: "指派给"
|
||||
fields:
|
||||
@@ -175,28 +171,21 @@ fields:
|
||||
format: ""
|
||||
- field: assignedDate
|
||||
note: "指派日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
range: "(M)-(w)"
|
||||
type: timestamp
|
||||
prefix: "DateTime"
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
format: "YY/MM/DD"
|
||||
- field: lastEditedBy
|
||||
note: "最后修改者"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: lastEditedDate
|
||||
note: "最后修改日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
range: ""
|
||||
- field: reviewedBy
|
||||
note: "评审者"
|
||||
fields:
|
||||
@@ -209,12 +198,7 @@ fields:
|
||||
format: ""
|
||||
- field: reviewedDate
|
||||
note: "评审日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
range: ""
|
||||
- field: closedBy
|
||||
note: "关闭者"
|
||||
fields:
|
||||
@@ -228,12 +212,7 @@ fields:
|
||||
format: ""
|
||||
- field: closedDate
|
||||
note: "关闭日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
range: ""
|
||||
- field: closedReason
|
||||
note: "关闭原因"
|
||||
range: done,subdivided,duplicate,postponed,willnotdo,cancel,bydesign
|
||||
|
||||
+24
-83
@@ -120,7 +120,6 @@ fields:
|
||||
range: "(+1w)-(-1M):-1D"
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
type: timestamp
|
||||
format: "YY/MM/DD"
|
||||
- field: status
|
||||
@@ -139,20 +138,14 @@ fields:
|
||||
format: ""
|
||||
- field: color
|
||||
note: "标题颜色"
|
||||
from: common.color.v1.yaml
|
||||
use: color
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: mailto
|
||||
note: "抄送给"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
range: ""
|
||||
- field: desc
|
||||
note: "任务描述"
|
||||
range: 1-10000
|
||||
@@ -169,20 +162,17 @@ fields:
|
||||
format: ""
|
||||
- field: openedBy
|
||||
note: "由谁创建"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: admin
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: openedDate
|
||||
note: "创建日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
range: "(M)-(w)"
|
||||
type: timestamp
|
||||
prefix: "DateTime"
|
||||
format: "YY/MM/DD"
|
||||
- field: assignedTo
|
||||
note: "指派给"
|
||||
range: ""
|
||||
@@ -192,12 +182,10 @@ fields:
|
||||
format: ""
|
||||
- field: assignedDate
|
||||
note: "指派日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
range: "(M)-(w)"
|
||||
type: timestamp
|
||||
prefix: "DateTime"
|
||||
format: "YY/MM/DD"
|
||||
- field: estStarted
|
||||
note: "预计开始"
|
||||
range: "2022-01-27"
|
||||
@@ -208,72 +196,39 @@ fields:
|
||||
format: "YY/MM/DD"
|
||||
- field: realStarted
|
||||
note: "实际开始"
|
||||
from: common.date.v1.yaml
|
||||
use: dateB
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: "YY/MM/DD"
|
||||
range: "(M)-(w)"
|
||||
type: timestamp
|
||||
prefix: "DateTime"
|
||||
format: "YY/MM/DD"
|
||||
- field: finishedBy
|
||||
note: "由谁完成"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: finishedDate
|
||||
note: "完成日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: "YY/MM/DD"
|
||||
type: timestamp
|
||||
range: ""
|
||||
- field: finishedList
|
||||
note: "完成者列表"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
range: ""
|
||||
- field: canceledBy
|
||||
note: "由谁取消"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
range: ""
|
||||
- field: canceledDate
|
||||
note: "取消日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: "YY/MM/DD"
|
||||
type: timestamp
|
||||
range: ""
|
||||
- field: closedBy
|
||||
note: "由谁关闭"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: closedDate
|
||||
note: "关闭日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: "YY/MM/DD"
|
||||
type: timestamp
|
||||
range: ""
|
||||
- field: realDuration
|
||||
note: "实际持续时长"
|
||||
range: 1
|
||||
@@ -297,30 +252,16 @@ fields:
|
||||
format: ""
|
||||
- field: lastEditedBy
|
||||
note: "最后修改者"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: lastEditedDate
|
||||
note: "最后修改时间"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: "YY/MM/DD"
|
||||
type: timestamp
|
||||
range: ""
|
||||
- field: activatedDate
|
||||
note: "重新激活日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateB
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: "YY/MM/DD"
|
||||
type: timestamp
|
||||
range: ""
|
||||
- field: deleted
|
||||
note: "是否删除"
|
||||
range: 0
|
||||
|
||||
@@ -30,16 +30,14 @@ fields:
|
||||
format: ""
|
||||
- field: estStarted
|
||||
note: "预计开始"
|
||||
from: common.date.v1.yaml
|
||||
use: dateB
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: deadline
|
||||
note: "截止时间"
|
||||
from: common.date.v1.yaml
|
||||
use: dateB
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
|
||||
+7
-15
@@ -16,7 +16,7 @@ fields:
|
||||
- field: account1
|
||||
range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},outside{100}
|
||||
- field: account2
|
||||
range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100
|
||||
range: "[],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100"
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
@@ -108,7 +108,7 @@ fields:
|
||||
- field: ass1
|
||||
range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},outside{100}
|
||||
- field: ass2
|
||||
range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100
|
||||
range: "[],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100"
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
format: ""
|
||||
@@ -118,7 +118,7 @@ fields:
|
||||
- field: ass1
|
||||
range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},outside{100}
|
||||
- field: ass2
|
||||
range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100
|
||||
range: "[],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100"
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
format: ""
|
||||
@@ -131,33 +131,25 @@ fields:
|
||||
format: "YY-MM-DD hh:mm:ss"
|
||||
- field: finishedBy
|
||||
note: "由谁完成"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: finishedDate
|
||||
note: "完成时间"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: closedBy
|
||||
note: "由谁关闭"
|
||||
from: common.user.v1.yaml
|
||||
use: user
|
||||
range: ""
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
- field: closedDate
|
||||
note: "关闭时间"
|
||||
from: common.date.v1.yaml
|
||||
use: dateA
|
||||
prefix: ""
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
range: ""
|
||||
|
||||
+7
-8
@@ -44,7 +44,7 @@ fields:
|
||||
- field: realname1
|
||||
range: admin,用户{99},测试{100},开发{100},项目经理{100},产品经理{100},研发主管{100},产品主管{100},测试主管{100},高层管理{100},外用户{100},其他{100},A,BB,CCC,非常长非常长的用户名怎么这么长?
|
||||
- field: realname2
|
||||
range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}
|
||||
range: "[],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}"
|
||||
- field: nickname
|
||||
note: "昵称"
|
||||
- field: commiter
|
||||
@@ -56,7 +56,7 @@ fields:
|
||||
range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}
|
||||
- field: avatar
|
||||
note: ""
|
||||
range: []
|
||||
range: ""
|
||||
format: ""
|
||||
- field: birthday
|
||||
note: "生日"
|
||||
@@ -123,12 +123,11 @@ fields:
|
||||
note: "邮编"
|
||||
- field: join
|
||||
note: "入职日期"
|
||||
from: common.date.v1.yaml
|
||||
use: dateB
|
||||
prefix: ""
|
||||
range: "(M)-(w)"
|
||||
type: timestamp
|
||||
prefix: "DateTime"
|
||||
postfix: ""
|
||||
loop: 0
|
||||
format: ""
|
||||
format: "YY/MM/DD"
|
||||
- field: visits
|
||||
note: "访问次数"
|
||||
range: 0-10000:R
|
||||
@@ -165,7 +164,7 @@ fields:
|
||||
- field: account1
|
||||
range: admin,user{99},test{100},dev{100},pm{100},po{100},td{100},pd{100},qd{100},top{100},outside{100},others{100},a,bb,ccc,qwuiadsd?!2as@#%$aasd~aj1!@#1
|
||||
- field: account2
|
||||
range: [],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}
|
||||
range: "[],1-99,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,1-100,[]{4}"
|
||||
- field: score
|
||||
note: "积分"
|
||||
range: 1-10000:R
|
||||
|
||||
+2
-3
@@ -102,9 +102,6 @@ function p($keys = '', $delimiter = ',')
|
||||
{
|
||||
global $_result;
|
||||
|
||||
$_keys = $keys;
|
||||
$_delimiter = $delimiter;
|
||||
|
||||
if(empty($_result)) return print(implode("\n", array_fill(0, substr_count($keys, $delimiter) + 1, 0)) . "\n");
|
||||
|
||||
if(is_array($_result) and isset($_result['code']) and $_result['code'] == 'fail') return print((string) $_result['message'] . "\n");
|
||||
@@ -117,6 +114,8 @@ function p($keys = '', $delimiter = ',')
|
||||
foreach($parts as $part)
|
||||
{
|
||||
$values = getValues($_result, $part, $delimiter);
|
||||
if(!is_array($values)) continue;
|
||||
|
||||
foreach($values as $value) echo $value . "\n";
|
||||
}
|
||||
|
||||
|
||||
+33
-30
@@ -341,21 +341,6 @@ class yaml
|
||||
$this->insertDB($yamlFile, $this->tableName, $rows, $isClear);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印zendata生成的sql和导入数据库产生的错误.
|
||||
* Print sql and error.
|
||||
*
|
||||
* @param int $rows
|
||||
* @param bool $isClear Truncate table if set isClear to true.
|
||||
* @param bool $debug Print sql and error if set isClear to true.
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function debug($rows, $isClear = true)
|
||||
{
|
||||
$yamlFile = $this->mergeYaml();
|
||||
$this->insertDB($yamlFile, $this->tableName, $rows, $isClear, true);
|
||||
}
|
||||
/**
|
||||
* Insert the data into database.
|
||||
*
|
||||
@@ -363,11 +348,10 @@ class yaml
|
||||
* @param string $tableName
|
||||
* @param int $rows
|
||||
* @param bool $isClear Truncate table if set isClear to true.
|
||||
* @param bool $debug
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
function insertDB($yamlFile, $tableName, $rows, $isClear = true, $debug = false)
|
||||
function insertDB($yamlFile, $tableName, $rows, $isClear = true)
|
||||
{
|
||||
$tableSqlDir = "{$_SERVER['PWD']}/data/sql";
|
||||
|
||||
@@ -385,32 +369,51 @@ class yaml
|
||||
$dbUser = $this->config->db->user;
|
||||
$dbPWD = $this->config->db->password;
|
||||
|
||||
$command = "$zdPath -c %s -d %s -n %d -t %s -dns mysql://%s:%s@%s:%s/%s#utf8";
|
||||
$command = "mysql -u%s -p%s -h%s -P%s -D%s < %s";
|
||||
$genSQL = "$zdPath -c %s -d %s -n %d -t %s -o %s";
|
||||
if($isClear === true)
|
||||
{
|
||||
/* Truncate table to reset auto increment number. */
|
||||
system(sprintf("mysql -u%s -p%s -h%s -P%s %s -e 'truncate %s' 2>/dev/null", $dbUser, $dbPWD, $dbHost, $dbPort, $dbName, $tableName));
|
||||
$command .= ' --clear';
|
||||
}
|
||||
$sqlPath = "{$tableSqlDir}/{$tableName}_zd.sql";
|
||||
$execYaml = sprintf($command, $configYaml, $yamlFile, $rows, $tableName, $dbUser, $dbPWD, $dbHost, $dbPort, $dbName);
|
||||
$execYaml = sprintf($command, $dbUser, $dbPWD, $dbHost, $dbPort, $dbName, $sqlPath);
|
||||
$execDump = sprintf($dumpCommand, $dbUser, $dbPWD, $dbHost, $dbPort, $dbName, $tableName);
|
||||
|
||||
$execGenSQL = sprintf($genSQL, $configYaml, $yamlFile, $rows, $tableName, $sqlPath);
|
||||
system($execGenSQL);
|
||||
|
||||
if($debug)
|
||||
{
|
||||
echo "\n" . file_get_contents($sqlPath) . "\n";
|
||||
|
||||
$tmpl = "mysql -u%s -p%s -h%s -P%s -D%s < %s";
|
||||
system(sprintf($tmpl, $dbUser, $dbPWD, $dbHost, $dbPort, $dbName, $sqlPath));
|
||||
return;
|
||||
}
|
||||
|
||||
system($execDump);
|
||||
system($execYaml);
|
||||
$stderr = '';
|
||||
$this->exec_with_stderr($execYaml, $stderr);
|
||||
|
||||
if(empty($stderr)) return;
|
||||
|
||||
$errors = explode(PHP_EOL, $stderr);
|
||||
$errors = array_filter($errors, function($error)
|
||||
{
|
||||
return !empty($error) && !strpos($error, 'Using a password on the command line interface can be insecure');
|
||||
});
|
||||
|
||||
if(!empty($errors)) echo implode(PHP_EOL, $errors) . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行系统命令,并捕捉stderror
|
||||
* exec command and catch stderror.
|
||||
*
|
||||
* @param string $cmd
|
||||
* @param string $stderr
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function exec_with_stderr($cmd, &$stderr=null)
|
||||
{
|
||||
$proc = proc_open($cmd, array(2 => array('pipe', 'w')), $pipes);
|
||||
$stderr = stream_get_contents($pipes[2]);
|
||||
|
||||
fclose($pipes[2]);
|
||||
proc_close($proc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+922
-61
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The functions of zin of ZenTaoPMS.
|
||||
*
|
||||
@@ -17,65 +18,925 @@ require_once __DIR__ . DS . 'zui' . DS . 'zui.func.php';
|
||||
require_once __DIR__ . DS . 'zentao' . DS . 'zentao.func.php';
|
||||
|
||||
/* Form */
|
||||
function input() {return createWg('input', func_get_args());}
|
||||
function textarea() {return createWg('textarea', func_get_args());}
|
||||
function radio() {return createWg('radio', func_get_args());}
|
||||
function switcher() {return createWg('switcher', func_get_args());}
|
||||
function checkbox() {return createWg('checkbox', func_get_args());}
|
||||
function form() {return createWg('form', func_get_args());}
|
||||
function formPanel() {return createWg('formPanel', func_get_args());}
|
||||
function control() {return createWg('control', func_get_args());}
|
||||
function select() {return createWg('select', func_get_args());}
|
||||
function formLabel() {return createWg('formLabel', func_get_args());}
|
||||
function formGroup() {return createWg('formGroup', func_get_args());}
|
||||
function formRow() {return createWg('formRow', func_get_args());}
|
||||
function inputControl() {return createWg('inputControl', func_get_args());}
|
||||
function inputGroup() {return createWg('inputGroup', func_get_args());}
|
||||
function checkList() {return createWg('checkList', func_get_args());}
|
||||
function radioList() {return createWg('radioList', func_get_args());}
|
||||
function colorPicker() {return createWg('colorPicker', func_get_args());}
|
||||
function datePicker() {return createWg('datePicker', func_get_args());}
|
||||
function datetimePicker() {return createWg('datetimePicker', func_get_args());}
|
||||
function timePicker() {return createWg('timePicker', func_get_args());}
|
||||
function fileInput() {return createWg('fileInput', func_get_args());}
|
||||
function pageForm() {return createWg('pageForm', func_get_args());}
|
||||
|
||||
function icon() {return createWg('icon', func_get_args());}
|
||||
function btn() {return createWg('btn', func_get_args());}
|
||||
function pageBase() {return createWg('pageBase', func_get_args());}
|
||||
function page() {return createWg('page', func_get_args());}
|
||||
function fragment() {return createWg('fragment', func_get_args());}
|
||||
function btnGroup() {return createWg('btnGroup', func_get_args());}
|
||||
function mainMenu() {return createWg('mainMenu', func_get_args());}
|
||||
function row() {return createWg('row', func_get_args());}
|
||||
function col() {return createWg('col', func_get_args());}
|
||||
function column() {return createWg('column', func_get_args());}
|
||||
function center() {return createWg('center', func_get_args());}
|
||||
function cell() {return createWg('cell', func_get_args());}
|
||||
function actionItem() {return createWg('actionItem', func_get_args());}
|
||||
function nav() {return createWg('nav', func_get_args());}
|
||||
function label() {return createWg('label', func_get_args());}
|
||||
function dtable() {return createWg('dtable', func_get_args());}
|
||||
function menu() {return createWg('menu', func_get_args());}
|
||||
function dropdown() {return createWg('dropdown', func_get_args());}
|
||||
function header() {return createWg('header', func_get_args());}
|
||||
function heading() {return createWg('heading', func_get_args());}
|
||||
function navbar() {return createWg('navbar', func_get_args());}
|
||||
function main() {return createWg('main', func_get_args());}
|
||||
function sidebar() {return createWg('sidebar', func_get_args());}
|
||||
function featureBar() {return createWg('featureBar', func_get_args());}
|
||||
function avatar() {return createWg('avatar', func_get_args());}
|
||||
function userAvatar() {return createWg('userAvatar', func_get_args());}
|
||||
function pager() {return createWg('pager', func_get_args());}
|
||||
function modal() {return createWg('modal', func_get_args());}
|
||||
function modalTrigger(){return createWg('modalTrigger', func_get_args());}
|
||||
function modalDialog() {return createWg('modalDialog', func_get_args());}
|
||||
function tabs() {return createWg('tabs', func_get_args());}
|
||||
function panel() {return createWg('panel', func_get_args());}
|
||||
function tooltip() {return createWg('tooltip', func_get_args());}
|
||||
function toolbar() {return createWg('toolbar', func_get_args());}
|
||||
function searchForm() {return createWg('searchForm', func_get_args());}
|
||||
function searchToggle(){return createWg('searchToggle', func_get_args());}
|
||||
function programMenu() {return createWg('programMenu', func_get_args());}
|
||||
function moduleMenu() {return createWg('moduleMenu', func_get_args());}
|
||||
function history() {return createWg('history', func_get_args());}
|
||||
/**
|
||||
* html input.
|
||||
*
|
||||
* string type='text'
|
||||
* string name
|
||||
* string id?
|
||||
* string class='form-control'
|
||||
* string value?
|
||||
* bool required?
|
||||
* string placeholder?
|
||||
* bool autofocus?
|
||||
* bool autocomplete=false
|
||||
* bool disabled
|
||||
*/
|
||||
function input()
|
||||
{
|
||||
return createWg('input', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* html textarea.
|
||||
*
|
||||
* string name
|
||||
* string id?
|
||||
* string class='form-control'
|
||||
* string value?
|
||||
* bool required?
|
||||
* string placeholder?
|
||||
* int rows
|
||||
* int cols
|
||||
*/
|
||||
function textarea()
|
||||
{
|
||||
return createWg('textarea', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* radio widget.
|
||||
*
|
||||
* string text?
|
||||
* bool checked?
|
||||
* string name?
|
||||
* bool primary=true
|
||||
* string id
|
||||
* bool disabled?
|
||||
* string value?
|
||||
* string typeClass?
|
||||
* string rootClass?
|
||||
*/
|
||||
function radio()
|
||||
{
|
||||
return createWg('radio', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* switcher widget.
|
||||
*
|
||||
* string text?
|
||||
* bool checked?
|
||||
* string name?
|
||||
* bool primary=true
|
||||
* string id
|
||||
* bool disabled?
|
||||
* string value
|
||||
* string typeClass?
|
||||
* string rootClass?
|
||||
*/
|
||||
function switcher()
|
||||
{
|
||||
return createWg('switcher', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* checkbox widget.
|
||||
*
|
||||
* string text?
|
||||
* bool checked?
|
||||
* string name?
|
||||
* bool primary=true
|
||||
* string id
|
||||
* bool disabled?
|
||||
* string value?
|
||||
* string typeClass?
|
||||
* string rootClass?
|
||||
*/
|
||||
function checkbox()
|
||||
{
|
||||
return createWg('checkbox', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* form widget.
|
||||
*
|
||||
* string method='post'
|
||||
* string url?
|
||||
* array actions?
|
||||
* string target?
|
||||
* array items?
|
||||
* bool grid?
|
||||
* int labelWidth?
|
||||
* string submitBtnText?
|
||||
* string cancelBtnText?
|
||||
*/
|
||||
function form()
|
||||
{
|
||||
return createWg('form', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* form panel widget.
|
||||
*
|
||||
* string method?
|
||||
* string url?
|
||||
* array actions?
|
||||
* string target?
|
||||
* array items?
|
||||
* bool grid?
|
||||
* int labelWidth?
|
||||
*/
|
||||
function formPanel()
|
||||
{
|
||||
return createWg('formPanel', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* control widget.
|
||||
* Dynamically create html input.
|
||||
*
|
||||
* string type - it can be text, password, email, number, date, time, datetime, month, url, search, tel, color, picker, select, checkbox, radio, checkboxList, radioList, checkboxListInline, radioListInline, file, textarea
|
||||
* string name
|
||||
* string id?
|
||||
* string value?
|
||||
* bool required?
|
||||
* string placeholder?
|
||||
* bool disabled?
|
||||
* string form?
|
||||
* array items?
|
||||
*/
|
||||
function control()
|
||||
{
|
||||
return createWg('control', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* html select.
|
||||
*
|
||||
* string name
|
||||
* string id?
|
||||
* string class="form-control"
|
||||
* string value?
|
||||
* bool required?
|
||||
* bool disabled?
|
||||
* bool multiple?
|
||||
* array items?
|
||||
* int size?
|
||||
*/
|
||||
function select()
|
||||
{
|
||||
return createWg('select', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* html label which use id form.
|
||||
*
|
||||
* string text?
|
||||
* bool required?
|
||||
* string for?
|
||||
*/
|
||||
function formLabel()
|
||||
{
|
||||
return createWg('formLabel', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* form group widget.
|
||||
*
|
||||
* string|array
|
||||
* string name?
|
||||
* string|bool label?
|
||||
* string labelClass?
|
||||
* bool|string required='auto'
|
||||
* string tip?
|
||||
* string|array tipClass?
|
||||
* array tipProps?
|
||||
* array|string control?
|
||||
* string width?
|
||||
* bool strong?
|
||||
* string|array value?
|
||||
* bool disabled?
|
||||
* array items?
|
||||
* string placeholder?
|
||||
*/
|
||||
function formGroup()
|
||||
{
|
||||
return createWg('formGroup', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* form row widget.
|
||||
*
|
||||
* string width?
|
||||
* array items?
|
||||
* bool hidden?
|
||||
*/
|
||||
function formRow()
|
||||
{
|
||||
return createWg('formRow', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* html input with prefix or suffix.
|
||||
*
|
||||
* mixed prefix
|
||||
* mixed suffix
|
||||
* string|int prefixWidth
|
||||
* string|int suffixWidth
|
||||
*/
|
||||
function inputControl()
|
||||
{
|
||||
return createWg('inputControl', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* input group widget.
|
||||
*
|
||||
* array items?
|
||||
* bool seg?
|
||||
*/
|
||||
function inputGroup()
|
||||
{
|
||||
return createWg('inputGroup', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* checkbox list widget.
|
||||
*
|
||||
* bool primary=true
|
||||
* string name?
|
||||
* string|array value?
|
||||
* array items
|
||||
* bool inline?
|
||||
*/
|
||||
function checkList()
|
||||
{
|
||||
return createWg('checkList', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* radio list widget.
|
||||
*
|
||||
* bool primary=true
|
||||
* string name?
|
||||
* string|array value?
|
||||
* array items
|
||||
* bool inline?
|
||||
*/
|
||||
function radioList()
|
||||
{
|
||||
return createWg('radioList', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* color picker widget which extends input.
|
||||
*
|
||||
* string name
|
||||
* string id?
|
||||
* string class?
|
||||
* string value?
|
||||
* bool required?
|
||||
* string placeholder?
|
||||
* bool autofocus?
|
||||
* bool autocomplete=false
|
||||
* bool disabled?
|
||||
*/
|
||||
function colorPicker()
|
||||
{
|
||||
return createWg('colorPicker', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* date picker widget which extends input.
|
||||
*
|
||||
* string name
|
||||
* string id?
|
||||
* string class?
|
||||
* string value?
|
||||
* bool required?
|
||||
* string placeholder?
|
||||
* bool autofocus?
|
||||
* bool autocomplete=false
|
||||
* bool disabled?
|
||||
*/
|
||||
function datePicker()
|
||||
{
|
||||
return createWg('datePicker', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* datetime picker widget which extends input.
|
||||
*
|
||||
* string name
|
||||
* string id?
|
||||
* string class?
|
||||
* string value?
|
||||
* bool required?
|
||||
* string placeholder?
|
||||
* bool autofocus?
|
||||
* bool autocomplete=false
|
||||
* bool disabled?
|
||||
*/
|
||||
function datetimePicker()
|
||||
{
|
||||
return createWg('datetimePicker', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* time picker widget which extends input.
|
||||
*
|
||||
* string name
|
||||
* string id?
|
||||
* string class?
|
||||
* string value?
|
||||
* bool required?
|
||||
* string placeholder?
|
||||
* bool autofocus?
|
||||
* bool autocomplete=false
|
||||
* bool disabled?
|
||||
*/
|
||||
function timePicker()
|
||||
{
|
||||
return createWg('timePicker', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* html file input which extends input.
|
||||
*
|
||||
* string name
|
||||
* string id?
|
||||
* string class?
|
||||
* string value?
|
||||
* bool required?
|
||||
* string placeholder?
|
||||
* bool autofocus?
|
||||
* bool autocomplete=false
|
||||
* bool disabled?
|
||||
*/
|
||||
function fileInput()
|
||||
{
|
||||
return createWg('fileInput', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* page form widget which extends page.
|
||||
*
|
||||
* array formPanel?
|
||||
* string|array metas=array('<meta charset="utf-8">', '<meta http-equiv="X-UA-Compatible" content="IE=edge">', '<meta name="viewport" content="width=device-width, initial-scale=1">', '<meta name="renderer" content="webkit">')
|
||||
* string title?
|
||||
* array bodyProps?
|
||||
* array|string bodyClass?
|
||||
* bool zui=true
|
||||
* bool display=true
|
||||
*
|
||||
* ====== blocks ======
|
||||
* head = array()
|
||||
* header = array('map' => 'header')
|
||||
* main = array('map' => 'main')
|
||||
* footer = array()
|
||||
* ====================
|
||||
*/
|
||||
function pageForm()
|
||||
{
|
||||
return createWg('pageForm', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* icon widget.
|
||||
*
|
||||
* string name
|
||||
* string|int size?
|
||||
*/
|
||||
function icon()
|
||||
{
|
||||
return createWg('icon', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* button widget.
|
||||
*
|
||||
* string icon?
|
||||
* string text?
|
||||
* bool square?
|
||||
* bool disabled?
|
||||
* bool active?
|
||||
* string url?
|
||||
* string target?
|
||||
* string|int size?
|
||||
* string trailingIcon?
|
||||
* string|bool caret?
|
||||
* string hint?
|
||||
* string type?
|
||||
* string btnType?
|
||||
*/
|
||||
function btn()
|
||||
{
|
||||
return createWg('btn', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* page base widget.
|
||||
*
|
||||
* string|array metas=array('<meta charset="utf-8">', '<meta http-equiv="X-UA-Compatible" content="IE=edge">', '<meta name="viewport" content="width=device-width, initial-scale=1">', '<meta name="renderer" content="webkit">')
|
||||
* string title?
|
||||
* array bodyProps?
|
||||
* array|string bodyClass?
|
||||
* bool zui=false
|
||||
* bool display=true
|
||||
*/
|
||||
function pageBase()
|
||||
{
|
||||
return createWg('pageBase', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* page widget.
|
||||
*
|
||||
* string|array metas=array('<meta charset="utf-8">', '<meta http-equiv="X-UA-Compatible" content="IE=edge">', '<meta name="viewport" content="width=device-width, initial-scale=1">', '<meta name="renderer" content="webkit">')
|
||||
* string title?
|
||||
* array bodyProps?
|
||||
* array|string bodyClass?
|
||||
* bool zui=true
|
||||
* bool display=true
|
||||
*
|
||||
* ====== blocks ======
|
||||
* head = array()
|
||||
* header = array('map' => 'header')
|
||||
* main = array('map' => 'main')
|
||||
* footer = array()
|
||||
* ====================
|
||||
*/
|
||||
function page()
|
||||
{
|
||||
return createWg('page', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* fragment widget.
|
||||
* lets you group elements without a wrapper node.
|
||||
*/
|
||||
function fragment()
|
||||
{
|
||||
return createWg('fragment', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* button group widget.
|
||||
*
|
||||
* array items?
|
||||
* bool disabled?
|
||||
* string size?
|
||||
*/
|
||||
function btnGroup()
|
||||
{
|
||||
return createWg('btnGroup', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* zentao main menu widget.
|
||||
*
|
||||
* array statuses?
|
||||
* array btnGroup?
|
||||
* array others?
|
||||
*/
|
||||
function mainMenu()
|
||||
{
|
||||
return createWg('mainMenu', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* row widget.
|
||||
*
|
||||
* string justify?
|
||||
* string align?
|
||||
*/
|
||||
function row()
|
||||
{
|
||||
return createWg('row', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* col widget.
|
||||
*
|
||||
* string justify?
|
||||
* string align?
|
||||
*/
|
||||
function col()
|
||||
{
|
||||
return createWg('col', func_get_args());
|
||||
}
|
||||
|
||||
function column()
|
||||
{
|
||||
return createWg('column', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* center widget.
|
||||
*/
|
||||
function center()
|
||||
{
|
||||
return createWg('center', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* cell widget.
|
||||
* flex item.
|
||||
*
|
||||
* int order
|
||||
* int grow
|
||||
* string shrink
|
||||
* string|int width 'auto'|'flex-start'|'flex-end'|'center'|'baseline'|'stretch'
|
||||
* string align
|
||||
* string flex
|
||||
*/
|
||||
function cell()
|
||||
{
|
||||
return createWg('cell', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* action item widget.
|
||||
*
|
||||
* string name='action'
|
||||
* string type='item'
|
||||
* string outerTag='li'
|
||||
* string tagName='a'
|
||||
* string icon?
|
||||
* string text?
|
||||
* string url?
|
||||
* string target?
|
||||
* bool active?
|
||||
* bool disabled?
|
||||
* string trailingIcon?
|
||||
* array outerProps?
|
||||
* string outerClass?
|
||||
* props array?
|
||||
* string|array|object badge?
|
||||
*/
|
||||
function actionItem()
|
||||
{
|
||||
return createWg('actionItem', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* nav widget.
|
||||
*
|
||||
* array items?
|
||||
*/
|
||||
function nav()
|
||||
{
|
||||
return createWg('nav', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* label widget.
|
||||
*
|
||||
* string text?
|
||||
*/
|
||||
function label()
|
||||
{
|
||||
return createWg('label', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* dtable widget.
|
||||
*/
|
||||
function dtable()
|
||||
{
|
||||
return createWg('dtable', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* menu widget.
|
||||
*
|
||||
* array items?
|
||||
*/
|
||||
function menu()
|
||||
{
|
||||
return createWg('menu', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* dropdown widget.
|
||||
*
|
||||
* array items?
|
||||
* string placement?
|
||||
* string strategy?
|
||||
* int offset?
|
||||
* bool flip?
|
||||
* string subMenuTrigger?
|
||||
* string arrow?
|
||||
* string trigger?
|
||||
* array menuProps?
|
||||
* string target?
|
||||
* string id?
|
||||
* string menuClass?
|
||||
* bool hasIcons?
|
||||
* bool staticMenu?
|
||||
*/
|
||||
function dropdown()
|
||||
{
|
||||
return createWg('dropdown', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* header widget.
|
||||
*
|
||||
* ====== blocks ======
|
||||
* heading = array('map' => 'toolbar')
|
||||
* navbar = array('map' => 'nav')
|
||||
* toolbar = array('map' => 'btn')
|
||||
* ====================
|
||||
*/
|
||||
function header()
|
||||
{
|
||||
return createWg('header', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* heading widget.
|
||||
*
|
||||
* array items
|
||||
* bool showAppName=true
|
||||
*/
|
||||
function heading()
|
||||
{
|
||||
return createWg('heading', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* navbar widget.
|
||||
*
|
||||
* array items?
|
||||
*/
|
||||
function navbar()
|
||||
{
|
||||
return createWg('navbar', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* main widget.
|
||||
*
|
||||
* ====== blocks ======
|
||||
* menu = array('map' => 'featureBar,nav,toolbar')
|
||||
* sidebar = array('map' => 'sidebar')
|
||||
* ====================
|
||||
*/
|
||||
function main()
|
||||
{
|
||||
return createWg('main', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* zentao sidebar widget.
|
||||
*
|
||||
* string side='left'
|
||||
* bool showToggle=true
|
||||
*/
|
||||
function sidebar()
|
||||
{
|
||||
return createWg('sidebar', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* zentao feature bar widget.
|
||||
*
|
||||
* array items?
|
||||
* string current?
|
||||
* string link?
|
||||
* string linkParams?
|
||||
*
|
||||
* ====== blocks ======
|
||||
* nav = array('map' => 'nav')
|
||||
* leading = array()
|
||||
* trailing = array()
|
||||
* ====================
|
||||
*/
|
||||
function featureBar()
|
||||
{
|
||||
return createWg('featureBar', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* avatar widget.
|
||||
*
|
||||
* string className?
|
||||
* array style?
|
||||
* int size=32
|
||||
* bool circle=true
|
||||
* string|int rounded?
|
||||
* string background?
|
||||
* string foreColor
|
||||
* string text?
|
||||
* string code?
|
||||
* int maxTextLength=2
|
||||
* int hueDistance=43
|
||||
* int saturation=0.4
|
||||
* int lightness=0.6
|
||||
* string src?
|
||||
*/
|
||||
function avatar()
|
||||
{
|
||||
return createWg('avatar', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* zentao user avatar widget.
|
||||
*
|
||||
* string className?
|
||||
* array style?
|
||||
* int size=32
|
||||
* bool circle=true
|
||||
* string|int rounded
|
||||
* string background
|
||||
* string foreColor
|
||||
* string text
|
||||
* string code?
|
||||
* int maxTextLength=2
|
||||
* int hueDistance=43
|
||||
* int saturation=0.4
|
||||
* int lightness=0.6
|
||||
* string src?
|
||||
* string avatar?
|
||||
* string account?
|
||||
* string realname?
|
||||
* array|object user?
|
||||
*/
|
||||
function userAvatar()
|
||||
{
|
||||
return createWg('userAvatar', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* pager widget.
|
||||
*/
|
||||
function pager()
|
||||
{
|
||||
return createWg('pager', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* modal widget.
|
||||
*
|
||||
* string id="$GID"
|
||||
* array modalProps=array()
|
||||
*/
|
||||
function modal()
|
||||
{
|
||||
return createWg('modal', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* modal trigger widget.
|
||||
*
|
||||
* string target?
|
||||
* string|int|object|function position?
|
||||
* string|int|object size?
|
||||
* bool|string backdrop?
|
||||
* bool keyboard?
|
||||
* bool moveable?
|
||||
* bool animation?
|
||||
* int transTime?
|
||||
* bool responsive?
|
||||
* string type?
|
||||
* string loadingText?
|
||||
* int loadTimeout?
|
||||
* string failedTip?
|
||||
* string timeoutTip?
|
||||
* string title?
|
||||
* string content?
|
||||
* object custom?
|
||||
* string url?
|
||||
* object request?
|
||||
* string dataType?
|
||||
*
|
||||
* ====== blocks ======
|
||||
* trigger = array('map' => 'btn,a')
|
||||
* modal = array('map' => 'modal')
|
||||
* ====================
|
||||
*/
|
||||
function modalTrigger()
|
||||
{
|
||||
return createWg('modalTrigger', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* modal dialog widget.
|
||||
*
|
||||
* string title?
|
||||
* int itemID?
|
||||
* string headerClass?
|
||||
* array headerProps?
|
||||
* array actions?
|
||||
* bool|array closeBtn=true
|
||||
* array footerActions
|
||||
* string footerClass
|
||||
* array footerProps
|
||||
*/
|
||||
function modalDialog()
|
||||
{
|
||||
return createWg('modalDialog', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* tabs widget.
|
||||
*
|
||||
* string direction='h'
|
||||
* array items
|
||||
* string activeId?
|
||||
*/
|
||||
function tabs()
|
||||
{
|
||||
return createWg('tabs', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* panel widget.
|
||||
*
|
||||
* string class='rounded shadow ring-0 canvas'
|
||||
* string size?
|
||||
* string title?
|
||||
* string titleClass?
|
||||
* array titleProps?
|
||||
* string headingClass?
|
||||
* array headingProps?
|
||||
* array headingActions?
|
||||
* string bodyClass?
|
||||
* array bodyProps?
|
||||
* array footerActions?
|
||||
* string footerClass?
|
||||
* array footerProps?
|
||||
*/
|
||||
function panel()
|
||||
{
|
||||
return createWg('panel', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* tooltip widget.
|
||||
*/
|
||||
function tooltip()
|
||||
{
|
||||
return createWg('tooltip', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* toolbar widget.
|
||||
*
|
||||
* array items?
|
||||
* string btnClass?
|
||||
* array btnProps?
|
||||
*/
|
||||
function toolbar()
|
||||
{
|
||||
return createWg('toolbar', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* zentao search form widget.
|
||||
*/
|
||||
function searchForm()
|
||||
{
|
||||
return createWg('searchForm', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* zentao search toggle widget.
|
||||
*
|
||||
* bool open?
|
||||
*/
|
||||
function searchToggle()
|
||||
{
|
||||
return createWg('searchToggle', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* zentao program menu widget.
|
||||
*
|
||||
* array programs?
|
||||
* string activeClass?
|
||||
* string activeIcon?
|
||||
* string activeKey?
|
||||
* string closeLink?
|
||||
*/
|
||||
function programMenu()
|
||||
{
|
||||
return createWg('programMenu', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* zentao module menu widget.
|
||||
*
|
||||
* int productID
|
||||
* int activeKey
|
||||
* string closeLink
|
||||
*/
|
||||
function moduleMenu()
|
||||
{
|
||||
return createWg('moduleMenu', func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* zentao history records widget.
|
||||
*
|
||||
* array actions?
|
||||
* array users?
|
||||
* string methodName?
|
||||
*/
|
||||
function history()
|
||||
{
|
||||
return createWg('history', func_get_args());
|
||||
}
|
||||
|
||||
@@ -8,8 +8,7 @@ require_once dirname(__DIR__) . DS . 'btngroup' . DS . 'v1.php';
|
||||
|
||||
class actionItem extends wg
|
||||
{
|
||||
static $defineProps = array
|
||||
(
|
||||
static $defineProps = array(
|
||||
'name:string="action"',
|
||||
'type:string="item"',
|
||||
'outerTag:string="li"',
|
||||
|
||||
+9
-10
@@ -3,21 +3,20 @@ namespace zin;
|
||||
|
||||
class avatar extends wg
|
||||
{
|
||||
protected static $defineProps = array
|
||||
(
|
||||
protected static $defineProps = array(
|
||||
'className?:string',
|
||||
'style?:array',
|
||||
'size?:number=32',
|
||||
'size?:int=32',
|
||||
'circle?:bool=true',
|
||||
'rounded?:string|number',
|
||||
'rounded?:string|int',
|
||||
'background?:string',
|
||||
'foreColor?:string',
|
||||
'text?:string',
|
||||
'code?:string',
|
||||
'maxTextLength?:number=2',
|
||||
'hueDistance?:number=43',
|
||||
'saturation?:number=0.4',
|
||||
'lightness?:number=0.6',
|
||||
'maxTextLength?:int=2',
|
||||
'hueDistance?:int=43',
|
||||
'saturation?:int=0.4',
|
||||
'lightness?:int=0.6',
|
||||
'src?:string'
|
||||
);
|
||||
|
||||
@@ -133,8 +132,8 @@ class avatar extends wg
|
||||
* Convert HSL values to RGB value.
|
||||
*
|
||||
* @param int $h
|
||||
* @param number $s
|
||||
* @param number $l
|
||||
* @param int $s
|
||||
* @param int $l
|
||||
* @access private
|
||||
* @return array
|
||||
*/
|
||||
|
||||
+3
-5
@@ -3,8 +3,7 @@ namespace zin;
|
||||
|
||||
class btn extends wg
|
||||
{
|
||||
static $defineProps = array
|
||||
(
|
||||
static $defineProps = array(
|
||||
'icon?:string',
|
||||
'text?:string',
|
||||
'square?:bool',
|
||||
@@ -12,7 +11,7 @@ class btn extends wg
|
||||
'active?:bool',
|
||||
'url?:string',
|
||||
'target?:string',
|
||||
'size?:string|number',
|
||||
'size?:string|int',
|
||||
'trailingIcon?:string',
|
||||
'caret?:string|bool',
|
||||
'hint?:string',
|
||||
@@ -80,8 +79,7 @@ class btn extends wg
|
||||
$trailingIcon = $this->prop('trailingIcon');
|
||||
$onlyCaret = empty($text) && !empty($caret) && empty($icon) && empty($trailingIcon);
|
||||
|
||||
$classList = array
|
||||
(
|
||||
$classList = array(
|
||||
'btn' => true,
|
||||
'disabled' => $this->prop('disabled'),
|
||||
'active' => $this->prop('active'),
|
||||
|
||||
+8
-1
@@ -4,7 +4,14 @@ namespace zin;
|
||||
|
||||
class cell extends wg
|
||||
{
|
||||
static $defineProps = 'order,grow,shrink,width,align,flex';
|
||||
static $defineProps = array(
|
||||
'order:int',
|
||||
'grow:int',
|
||||
'shrink:int',
|
||||
'width:string|int',
|
||||
'align:string', //'auto'|'flex-start'|'flex-end'|'center'|'baseline'|'stretch'
|
||||
'flex:string'
|
||||
);
|
||||
|
||||
protected function build()
|
||||
{
|
||||
|
||||
+4
-1
@@ -4,7 +4,10 @@ namespace zin;
|
||||
|
||||
class col extends wg
|
||||
{
|
||||
static $defineProps = 'justify?:string,align?:string';
|
||||
static $defineProps = array(
|
||||
'justify?:string',
|
||||
'align?:string'
|
||||
);
|
||||
|
||||
protected function build()
|
||||
{
|
||||
|
||||
+16
-1
@@ -6,7 +6,22 @@ require_once dirname(__DIR__) . DS . 'btn' . DS . 'v1.php';
|
||||
|
||||
class dropdown extends wg
|
||||
{
|
||||
static $defineProps = 'items?:array, placement?:string, strategy?:string, offset?: number, flip?: bool, subMenuTrigger?: string, arrow?: string, trigger?: string, menuProps?: array, target?: string, id?: string, menuClass?: string, hasIcons?: bool, staticMenu?: bool';
|
||||
static $defineProps = array(
|
||||
'items?:array',
|
||||
'placement?:string',
|
||||
'strategy?:string',
|
||||
'offset?: int',
|
||||
'flip?: bool',
|
||||
'subMenuTrigger?: string',
|
||||
'arrow?: string',
|
||||
'trigger?: string',
|
||||
'menuProps?: array',
|
||||
'target?: string',
|
||||
'id?: string',
|
||||
'menuClass?: string',
|
||||
'hasIcons?: bool',
|
||||
'staticMenu?: bool'
|
||||
);
|
||||
|
||||
static $defineBlocks = array
|
||||
(
|
||||
|
||||
@@ -3,7 +3,10 @@ namespace zin;
|
||||
|
||||
class dtable extends wg
|
||||
{
|
||||
static $defineProps = 'className?:string="shadow-sm rounded", id?:string';
|
||||
static $defineProps = array(
|
||||
'className?:string="shadow-sm rounded"',
|
||||
'id?:string'
|
||||
);
|
||||
|
||||
static $dtableID = 0;
|
||||
|
||||
|
||||
@@ -5,7 +5,12 @@ require_once dirname(__DIR__) . DS . 'nav' . DS . 'v1.php';
|
||||
|
||||
class featureBar extends wg
|
||||
{
|
||||
static $defineProps = 'items?:array, current?:string, link?:string, linkParams?:string';
|
||||
static $defineProps = array(
|
||||
'items?:array',
|
||||
'current?:string',
|
||||
'link?:string',
|
||||
'linkParams?:string'
|
||||
);
|
||||
|
||||
static $defineBlocks = array
|
||||
(
|
||||
@@ -28,7 +33,7 @@ class featureBar extends wg
|
||||
$rawItems = \customModel::getFeatureMenu($app->rawModule, $app->rawMethod);
|
||||
if(!is_array($rawItems)) return NULL;
|
||||
|
||||
$current = $this->prop('current', data('browseType', ''));
|
||||
$current = $this->prop('current', data('browseType'));
|
||||
$recTotal = data('recTotal');
|
||||
$items = array();
|
||||
$link = $this->prop('link');
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ class form extends wg
|
||||
'target?: string',
|
||||
'items?: array',
|
||||
'grid?: bool',
|
||||
'labelWidth?: number',
|
||||
'labelWidth?: int',
|
||||
'submitBtnText?: string',
|
||||
'cancelBtnText?: string',
|
||||
);
|
||||
|
||||
@@ -6,8 +6,7 @@ require_once dirname(__DIR__) . DS . 'control' . DS . 'v1.php';
|
||||
|
||||
class formGroup extends wg
|
||||
{
|
||||
protected static $defineProps = array
|
||||
(
|
||||
protected static $defineProps = array(
|
||||
'name?: string',
|
||||
'label?:string|bool',
|
||||
'labelClass?: string',
|
||||
|
||||
@@ -3,7 +3,11 @@ namespace zin;
|
||||
|
||||
class formLabel extends wg
|
||||
{
|
||||
protected static $defineProps = 'text?:string, required?:bool, for?: string';
|
||||
protected static $defineProps = array(
|
||||
'text?:string',
|
||||
'required?:bool',
|
||||
'for?:string'
|
||||
);
|
||||
|
||||
public function onAddChild($child)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ class formPanel extends panel
|
||||
'target?: string',
|
||||
'items?: array',
|
||||
'grid?: bool',
|
||||
'labelWidth?: number',
|
||||
'labelWidth?: int',
|
||||
);
|
||||
|
||||
protected static $defaultProps = array(
|
||||
|
||||
@@ -5,7 +5,11 @@ require_once dirname(__DIR__) . DS . 'formgroup' . DS . 'v1.php';
|
||||
|
||||
class formRow extends wg
|
||||
{
|
||||
static $defineProps = 'width?: string, items?: array, hidden?: boolean';
|
||||
static $defineProps = array(
|
||||
'width?: string',
|
||||
'items?: array',
|
||||
'hidden?: boolean'
|
||||
);
|
||||
|
||||
public function onBuildItem($item)
|
||||
{
|
||||
|
||||
@@ -8,8 +8,7 @@ require_once dirname(__DIR__) . DS . 'useravatar' . DS . 'v1.php';
|
||||
|
||||
class header extends wg
|
||||
{
|
||||
static $defineBlocks = array
|
||||
(
|
||||
static $defineBlocks = array(
|
||||
'heading' => array('map' => 'toolbar'),
|
||||
'navbar' => array('map' => 'nav'),
|
||||
'toolbar' => array('map' => 'btn')
|
||||
|
||||
@@ -5,7 +5,10 @@ require_once dirname(__DIR__) . DS . 'toolbar' . DS . 'v1.php';
|
||||
|
||||
class heading extends wg
|
||||
{
|
||||
static $defineProps = 'items?:array, showAppName?:bool=true';
|
||||
static $defineProps = array(
|
||||
'items?:array',
|
||||
'showAppName?:bool=true'
|
||||
);
|
||||
|
||||
protected function buildAppName()
|
||||
{
|
||||
|
||||
+4
-1
@@ -3,7 +3,10 @@ namespace zin;
|
||||
|
||||
class icon extends wg
|
||||
{
|
||||
protected static $defineProps = 'name:string, size?:string|number';
|
||||
protected static $defineProps = array(
|
||||
'name:string',
|
||||
'size?:string|int'
|
||||
);
|
||||
|
||||
public function onAddChild($child)
|
||||
{
|
||||
|
||||
@@ -8,8 +8,8 @@ class inputControl extends wg
|
||||
protected static $defineProps = array(
|
||||
'prefix?: mixed',
|
||||
'suffix?: mixed',
|
||||
'prefixWidth?: string|number',
|
||||
'suffixWidth?: string|number',
|
||||
'prefixWidth?: string|int',
|
||||
'suffixWidth?: string|int',
|
||||
);
|
||||
|
||||
public static $defineBlocks = array(
|
||||
|
||||
+1
-2
@@ -6,8 +6,7 @@ require_once dirname(__DIR__) . DS . 'featurebar' . DS . 'v1.php';
|
||||
|
||||
class main extends wg
|
||||
{
|
||||
static $defineBlocks = array
|
||||
(
|
||||
static $defineBlocks = array(
|
||||
'menu' => array('map' => 'featureBar,nav,toolbar'),
|
||||
'sidebar' => array('map' => 'sidebar')
|
||||
);
|
||||
|
||||
@@ -4,7 +4,11 @@ namespace zin;
|
||||
|
||||
class mainMenu extends wg
|
||||
{
|
||||
static $defineProps = 'statuses?:array,btnGroup?:array,others?:array';
|
||||
static $defineProps = array(
|
||||
'statuses?:array',
|
||||
'btnGroup?:array',
|
||||
'others?:array'
|
||||
);
|
||||
|
||||
protected function buildOther($item)
|
||||
{
|
||||
|
||||
+4
-1
@@ -5,7 +5,10 @@ require_once dirname(__DIR__) . DS . 'modaldialog' . DS . 'v1.php';
|
||||
|
||||
class modal extends modalDialog
|
||||
{
|
||||
static $defineProps = 'id?: string="$GID", modalProps?: array=[]';
|
||||
static $defineProps = array(
|
||||
'id?: string="$GID"',
|
||||
'modalProps?: array=array()'
|
||||
);
|
||||
|
||||
protected function build()
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user