Merge branch '18.4' of https://git.zcorp.cc/easycorp/zentaopms into zentaoipd

This commit is contained in:
tanghucheng
2023-04-28 13:10:24 +08:00
246 changed files with 6392 additions and 2381 deletions
+3 -3
View File
@@ -236,9 +236,9 @@ $config->openMethods[] = 'caselib.index';
$config->openMethods[] = 'company.index';
$config->openMethods[] = 'user.cropAvatar';
$config->openMethods[] = 'custom.index';
$config->openMethods[] = 'testcase.getXmindImport';
$config->openMethods[] = 'testcase.showXMindImport';
$config->openMethods[] = 'testcase.saveXmindImport';
$config->openMethods[] = 'testcase.getxmindimport';
$config->openMethods[] = 'testcase.showxmindimport';
$config->openMethods[] = 'testcase.savexmindimport';
$config->openModules = array();
$config->openModules[] = 'install';
+2652 -21
View File
File diff suppressed because one or more lines are too long
+10 -10
View File
@@ -4332,16 +4332,16 @@ REPLACE INTO `zt_basicmeas` VALUES
(41,'workload','project','finance','项目设计工作实际消耗工时数','pgmDesignRealHours','小时','CREATE FUNCTION `qc_pgmdesignrealhours`($project int) RETURNS float(10,2)\r\nBEGIN\r\nreturn qc_pgmrealhoursbytype($project, \'design\')__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目所有设计相关任务的实际消耗工时和','从任务表中查询该项目所有任务类型为设计的任务,统计实际消耗工时,求和。','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','system','0000-00-00 00:00:00','admin','2020-07-07 19:48:35',205,'0'),
(42,'workload','project','finance','项目开发工作实际消耗工时数','pgmDevelRealHours','小时','CREATE FUNCTION `qc_pgmdevelrealhours`($project int) RETURNS float(10,2)\r\nBEGIN\r\nreturn qc_pgmrealhoursbytype($project, \'devel\')__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目所有开发相关任务的实际消耗工时和','从任务表中查询该项目所有任务类型为开发的任务,统计实际消耗工时,求和。','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','system','0000-00-00 00:00:00','admin','2020-07-07 18:34:51',210,'0'),
(43,'workload','project','finance','项目测试工作实际消耗工时数','pgmTestRealHours','小时','CREATE FUNCTION `qc_pgmtestrealhours`($project int) RETURNS float(10, 2)\r\nBEGIN\r\nreturn qc_pgmrealhoursbytype($project, \'test\')__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目所有测试相关任务的实际消耗工时和','从任务表中查询该项目所有任务类型为测试的任务,统计实际消耗工时,求和。','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','system','0000-00-00 00:00:00','admin','2020-07-07 18:09:01',215,'0'),
(44,'workload','project','finance','项目开发工作最初总预计工时数','pgmDevelFirstEstHours','小时','CREATE FUNCTION `qc_pgmdevelfirstesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getdevelfirstesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划第一个基线版本中所有开发相关工作最初预计工时和',NULL,'crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-22 13:13:51','','0000-00-00 00:00:00',220,'0'),
(45,'workload','project','finance','项目设计工作最初总预计工时数','pgmDesignFirstEstHours','小时','CREATE FUNCTION `qc_pgmdesignfirstesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getdesignfirstesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划第一个基线版本中所有设计相关工作最初预计工时和',NULL,'crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-22 16:33:20','admin','2020-07-23 10:31:23',225,'0'),
(46,'workload','project','finance','项目测试工作最初总预计工时数','pgmTestFirstEstHours','小时','CREATE FUNCTION `qc_pgmtestfirstesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_gettestfirstesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划第一个基线版本中所有测试相关工作最初预计工时和',NULL,'crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 10:31:17','','0000-00-00 00:00:00',230,'0'),
(47,'workload','project','finance','项目需求工作最初总预计工时数','pgmRequestFirstEstHours','小时','CREATE FUNCTION `qc_pgmrequestfirstesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getstoryfirstesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划第一个基线版本中所有需求相关工作最初预计工时和',NULL,'crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 10:53:09','','0000-00-00 00:00:00',235,'0'),
(48,'workload','project','finance','项目任务最初总预计工时数','pgmFirstEstHours','小时','CREATE FUNCTION `qc_pgmfirstesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getfirstesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划第一个基线版本中所有任务最初预计工时和',NULL,'crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 13:06:59','','0000-00-00 00:00:00',240,'0'),
(49,'workload','project','finance','项目开发工作最终总预计工时数','pgmDevelLastEstHours','小时','CREATE FUNCTION `qc_pgmdevellastesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getdevlastesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划最后一个基线版本中所有开发相关任务最初预计工时和',NULL,'crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 13:41:38','','0000-00-00 00:00:00',245,'0'),
(50,'workload','project','finance','项目需求工作最终总预计工时数','pgmRequestLastEstHours','小时','CREATE FUNCTION `qc_pgmrequestlastesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project,\'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getrequestlastesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划最后一个基线版本中所有需求相关任务最初预计工时和',NULL,'crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 14:00:58','','0000-00-00 00:00:00',250,'0'),
(51,'workload','project','finance','项目测试工作最终总预计工时数','pgmTestLastEstHours','小时','CREATE FUNCTION `qc_pgmtestlastesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project,\'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_gettestlastesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划最后一个基线版本中所有测试相关任务最初预计工时和',NULL,'crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 14:10:12','','0000-00-00 00:00:00',255,'0'),
(52,'workload','project','finance','项目设计工作最终总预计工时数','pgmDesignLastEstHours','小时','CREATE FUNCTION `qc_pgmdesignlastesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project,\'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getdesignlastesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划最后一个基线版本中所有设计相关任务最初预计工时和',NULL,'crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 14:33:00','','0000-00-00 00:00:00',260,'0'),
(53,'workload','project','finance','项目任务最终总预计工时数','pgmLastEstHours','小时','CREATE FUNCTION `qc_pgmlastesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project,\'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getlastesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划最后一个基线版本中所有任务最初预计工时和',NULL,'crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 14:54:42','','0000-00-00 00:00:00',265,'0');
(44,'workload','project','finance','项目开发工作最初总预计工时数','pgmDevelFirstEstHours','小时','CREATE FUNCTION `qc_pgmdevelfirstesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getdevelfirstesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划第一个基线版本中所有开发相关工作最初预计工时和','','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-22 13:13:51','','0000-00-00 00:00:00',220,'0'),
(45,'workload','project','finance','项目设计工作最初总预计工时数','pgmDesignFirstEstHours','小时','CREATE FUNCTION `qc_pgmdesignfirstesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getdesignfirstesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划第一个基线版本中所有设计相关工作最初预计工时和','','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-22 16:33:20','admin','2020-07-23 10:31:23',225,'0'),
(46,'workload','project','finance','项目测试工作最初总预计工时数','pgmTestFirstEstHours','小时','CREATE FUNCTION `qc_pgmtestfirstesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_gettestfirstesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划第一个基线版本中所有测试相关工作最初预计工时和','','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 10:31:17','','0000-00-00 00:00:00',230,'0'),
(47,'workload','project','finance','项目需求工作最初总预计工时数','pgmRequestFirstEstHours','小时','CREATE FUNCTION `qc_pgmrequestfirstesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getstoryfirstesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划第一个基线版本中所有需求相关工作最初预计工时和','','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 10:53:09','','0000-00-00 00:00:00',235,'0'),
(48,'workload','project','finance','项目任务最初总预计工时数','pgmFirstEstHours','小时','CREATE FUNCTION `qc_pgmfirstesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getfirstesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划第一个基线版本中所有任务最初预计工时和','','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 13:06:59','','0000-00-00 00:00:00',240,'0'),
(49,'workload','project','finance','项目开发工作最终总预计工时数','pgmDevelLastEstHours','小时','CREATE FUNCTION `qc_pgmdevellastesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project, \'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getdevlastesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划最后一个基线版本中所有开发相关任务最初预计工时和','','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 13:41:38','','0000-00-00 00:00:00',245,'0'),
(50,'workload','project','finance','项目需求工作最终总预计工时数','pgmRequestLastEstHours','小时','CREATE FUNCTION `qc_pgmrequestlastesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project,\'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getrequestlastesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划最后一个基线版本中所有需求相关任务最初预计工时和','','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 14:00:58','','0000-00-00 00:00:00',250,'0'),
(51,'workload','project','finance','项目测试工作最终总预计工时数','pgmTestLastEstHours','小时','CREATE FUNCTION `qc_pgmtestlastesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project,\'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_gettestlastesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划最后一个基线版本中所有测试相关任务最初预计工时和','','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 14:10:12','','0000-00-00 00:00:00',255,'0'),
(52,'workload','project','finance','项目设计工作最终总预计工时数','pgmDesignLastEstHours','小时','CREATE FUNCTION `qc_pgmdesignlastesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project,\'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getdesignlastesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划最后一个基线版本中所有设计相关任务最初预计工时和','','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 14:33:00','','0000-00-00 00:00:00',260,'0'),
(53,'workload','project','finance','项目任务最终总预计工时数','pgmLastEstHours','小时','CREATE FUNCTION `qc_pgmlastesthours`($project int) RETURNS float(10,2)\r\nBEGIN\r\n declare estimate float(10,2) default 0__DELIMITER__\r\n declare inited int default 0__DELIMITER__\r\n select qc_cminited($project,\'PP\') into inited__DELIMITER__\r\n IF inited = 1 THEN\r\n select qc_getlastesthours($project) into estimate__DELIMITER__\r\n return estimate__DELIMITER__\r\n ELSE \r\n return 0__DELIMITER__\r\n END IF__DELIMITER__\r\nEND','{\"$project\":{\"showName\":\"\\u6240\\u5c5e\\u9879\\u76ee\",\"varName\":\"$project\",\"varType\":\"select\",\"options\":\"project\",\"defaultValue\":\"\"}}','项目计划最后一个基线版本中所有任务最初预计工时和','','crontab','{\"week\":\"1,2,3,4,5,6,0\",\"type\":\"week\"}','00:00','','admin','2020-07-23 14:54:42','','0000-00-00 00:00:00',265,'0');
REPLACE INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`, `lastTime`) VALUES
('1','0','*','*','*','moduleName=weekly&methodName=computeWeekly','更新项目周报','system',0,'normal','2020-08-27 10:07:53'),
+360 -270
View File
File diff suppressed because one or more lines are too long
+696 -386
View File
File diff suppressed because it is too large Load Diff
@@ -921,6 +921,48 @@ $lang->cron->methodOrder[25] = 'toggle';
$lang->cron->methodOrder[30] = 'delete';
$lang->cron->methodOrder[35] = 'openProcess';
$lang->resource->contact = new stdclass();
$lang->resource->programstakeholder = new stdclass();
$lang->resource->researchplan = new stdclass();
$lang->resource->workestimation = new stdclass();
$lang->resource->gapanalysis = new stdclass();
$lang->resource->executionview = new stdclass();
$lang->resource->managespace = new stdclass();
$lang->resource->systemteam = new stdclass();
$lang->resource->systemschedule = new stdclass();
$lang->resource->systemeffort = new stdclass();
$lang->resource->systemdynamic = new stdclass();
$lang->resource->systemcompany = new stdclass();
$lang->resource->pipeline = new stdclass();
$lang->resource->devopssetting = new stdclass();
$lang->resource->featureswitch = new stdclass();
$lang->resource->importdata = new stdclass();
$lang->resource->systemsetting = new stdclass();
$lang->resource->staffmanage = new stdclass();
$lang->resource->modelconfig = new stdclass();
$lang->resource->featureconfig = new stdclass();
$lang->resource->doctemplate = new stdclass();
$lang->resource->notifysetting = new stdclass();
$lang->resource->bidesign = new stdclass();
$lang->resource->personalsettings = new stdclass();
$lang->resource->projectsettings = new stdclass();
$lang->resource->dataaccess = new stdclass();
$lang->resource->executiongantt = new stdclass();
$lang->resource->executionkanban = new stdclass();
$lang->resource->executionburn = new stdclass();
$lang->resource->executioncfd = new stdclass();
$lang->resource->executionstory = new stdclass();
$lang->resource->executionqa = new stdclass();
$lang->resource->executionsettings = new stdclass();
$lang->resource->generalcomment = new stdclass();
$lang->resource->generalping = new stdclass();
$lang->resource->generaltemplate = new stdclass();
$lang->resource->generaleffort = new stdclass();
$lang->resource->productsettings = new stdclass();
$lang->resource->projectreview = new stdclass();
$lang->resource->projecttrack = new stdclass();
$lang->resource->projectqa = new stdclass();
if($config->edition == 'biz' or $config->edition == 'max')
{
/* My module. */
@@ -25,7 +25,7 @@ public function getPairs($mode = '', $programID = 0, $append = '', $shadow = 0)
->andWhere('t2.vision')->eq($this->config->vision)
->fetchPairs('id', 'id');
$products = $this->dao->select('*, IF(INSTR(" closed", status) < 2, 0, 1) AS isClosed')
$products = $this->dao->select("*, IF(INSTR(' closed', status) < 2, 0, 1) AS isClosed")
->from(TABLE_PRODUCT)
->where(1)
->beginIF(strpos($mode, 'all') === false)->andWhere('deleted')->eq(0)->fi()
+3 -9
View File
@@ -799,7 +799,6 @@ class baseControl
$moduleControlFile = $modulePath . 'control.php';
$actionExtPath = $this->app->getModuleExtPath($appName, $moduleName, 'control');
$file2Included = $moduleControlFile;
$classNameToFetch = $moduleName;
if(!empty($actionExtPath))
{
@@ -845,9 +844,6 @@ class baseControl
$siteActionExtFile = $actionExtPath['site'] . strtolower($methodName) . '.php';
$file2Included = file_exists($siteActionExtFile) ? $siteActionExtFile : $file2Included;
}
/* If class name is my{$moduleName} then set classNameToFetch for include this file. */
if(strpos($file2Included, DS . 'ext' . DS) !== false and stripos(file_get_contents($file2Included), "class my{$moduleName} extends $moduleName") !== false) $classNameToFetch = "my{$moduleName}";
}
/**
@@ -855,11 +851,9 @@ class baseControl
* Load the control file.
*/
if(!is_file($file2Included)) $this->app->triggerError("The control file $file2Included not found", __FILE__, __LINE__, $exit = true);
if(!class_exists($classNameToFetch))
{
chdir(dirname($file2Included));
helper::import($file2Included);
}
chdir(dirname($file2Included));
helper::import($file2Included);
/**
* 设置调用的类名。
+5 -5
View File
@@ -35,7 +35,7 @@ class control extends baseControl
$this->app->setOpenApp();
if(!isset($this->config->bizVersion)) return false;
if($this->config->edition == 'open') return false;
/* Code for task #9224. Set requiredFields for workflow. */
if($this->dbh and (defined('IN_USE') or (defined('RUN_MODE') and RUN_MODE == 'api')))
@@ -424,7 +424,7 @@ class control extends baseControl
*/
public function buildOperateMenu($object, $type = 'view')
{
if(!isset($this->config->bizVersion)) return false;
if($this->config->edition == 'open') return false;
$moduleName = $this->moduleName;
return $this->$moduleName->buildOperateMenu($object, $type);
@@ -439,7 +439,7 @@ class control extends baseControl
*/
public function executeHooks($objectID)
{
if(!isset($this->config->bizVersion)) return false;
if($this->config->edition == 'open') return false;
$moduleName = $this->moduleName;
return $this->$moduleName->executeHooks($objectID);
@@ -454,7 +454,7 @@ class control extends baseControl
*/
public function getFlowExportFields()
{
if(!isset($this->config->bizVersion)) return array();
if($this->config->edition == 'open') return array();
$moduleName = $this->moduleName;
return $this->$moduleName->getFlowExportFields();
@@ -478,7 +478,7 @@ class control extends baseControl
*/
public function printExtendFields($object, $type, $extras = '', $print = true, $moduleName = '', $methodName = '')
{
if(!isset($this->config->bizVersion)) return false;
if($this->config->edition == 'open') return false;
$moduleName = $moduleName ? $moduleName : $this->app->getModuleName();
$methodName = $methodName ? $methodName : $this->app->getMethodName();
+9 -9
View File
@@ -99,7 +99,7 @@ class model extends baseModel
if(empty($method)) $method = $methodName;
static $actions = array();
if(isset($this->config->bizVersion))
if($this->config->edition != 'open')
{
if(empty($actions[$moduleName]))
{
@@ -155,7 +155,7 @@ class model extends baseModel
*/
public function buildFlowMenu($module, $data, $type = 'browse', $show = '')
{
if(!isset($this->config->bizVersion)) return '';
if($this->config->edition == 'open') return '';
$moduleName = $module;
if(strpos($module, '.') !== false) list($appName, $moduleName) = explode('.', $module);
@@ -233,7 +233,7 @@ class model extends baseModel
*/
public function processStatus($module, $record)
{
if(!isset($this->config->bizVersion) or empty($record->subStatus)) return zget($this->lang->$module->statusList, $record->status);
if($this->config->edition == 'open' or empty($record->subStatus)) return zget($this->lang->$module->statusList, $record->status);
return $this->loadModel('workflowfield')->processSubStatus($module, $record);
}
@@ -247,7 +247,7 @@ class model extends baseModel
*/
public function processExportData($data)
{
if(!isset($this->config->bizVersion)) return $data;
if($this->config->edition == 'open') return $data;
return $this->loadModel('workflowfield')->processExportData($data);
}
@@ -261,7 +261,7 @@ class model extends baseModel
*/
public function processExportOptions($data)
{
if(!isset($this->config->bizVersion)) return $data;
if($this->config->edition == 'open') return $data;
return $this->loadModel('workflowfield')->processExportOptions($data);
}
@@ -275,7 +275,7 @@ class model extends baseModel
*/
public function processImportData($data)
{
if(!isset($this->config->bizVersion)) return $data;
if($this->config->edition == 'open') return $data;
return $this->loadModel('workflowfield')->processImportData($data);
}
@@ -288,7 +288,7 @@ class model extends baseModel
*/
public function getFlowExtendFields()
{
if(!isset($this->config->bizVersion)) return array();
if($this->config->edition == 'open') return array();
return $this->loadModel('flow')->getExtendFields($this->app->getModuleName(), $this->app->getMethodName());
}
@@ -301,7 +301,7 @@ class model extends baseModel
*/
public function getFlowExportFields()
{
if(!isset($this->config->bizVersion)) return array();
if($this->config->edition == 'open') return array();
return $this->loadModel('workflowfield')->getExportFields($this->app->getModuleName());
}
@@ -315,7 +315,7 @@ class model extends baseModel
*/
public function executeHooks($objectID)
{
if(!isset($this->config->bizVersion)) return false;
if($this->config->edition == 'open') return false;
$moduleName = $this->app->getModuleName();
$methodName = $this->app->getMethodName();
+1 -1
View File
@@ -478,7 +478,7 @@ class router extends baseRouter
if(empty($this->rawMethod)) $this->rawMethod = $this->methodName;
/* If is not a biz version or is in install mode or in in upgrade mode, call parent method. */
if(!isset($this->config->bizVersion) or defined('IN_INSTALL') or defined('IN_UPGRADE')) return parent::setControlFile($exitIfNone);
if($this->config->edition == 'open' or defined('IN_INSTALL') or defined('IN_UPGRADE')) return parent::setControlFile($exitIfNone);
/* Check if the requested module is defined in workflow. */
$flow = $this->dbh->query("SELECT * FROM " . TABLE_WORKFLOW . " WHERE `module` = '$this->moduleName'")->fetch();
+1
View File
@@ -920,6 +920,7 @@ class baseDAO
{
$rows = $stmt->fetchAll();
$result = array();
if(!$rows) $rows = array();
dao::$cache[$table][$key] = $rows;
foreach($rows as $i => $row) $result[$i] = $this->getRow($row);
return $result;
+3 -3
View File
@@ -526,10 +526,10 @@ class baseHTML
/* If the link of the referer is not the link of the current page or the link of the index, the cookie and gobackLink will be updated. */
if(preg_match("/(?:m=|\/)([a-zA-Z0-9]+)(?:(&f=)|(-?))([a-zA-Z0-9]+)?(?:&|-|\.)?/", strtolower($refererLink), $matches))
{
if(!isset($matches[2])) $matches[2] = $config->default->method;
if(!in_array($matches[1], array($config->default->module, 'search')) or !in_array($matches[2], array($config->default->method, 'buildquery')))
if(!isset($matches[4])) $matches[4] = $config->default->method;
if(!in_array($matches[1], array($config->default->module, 'search')) or !in_array($matches[4], array($config->default->method, 'buildquery')))
{
if($matches[1] != $currentModule or $matches[2] != $currentMethod)
if($matches[1] != 'index' and ($matches[1] != $currentModule or $matches[4] != $currentMethod))
{
$gobackList[$tab] = $referer;
$gobackLink = $referer;
-516
View File
@@ -1,516 +0,0 @@
<?php
/**
* ZenTaoPHP的dao和sql类。
* The dao and sql class file of ZenTaoPHP framework.
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
/**
* Dameng类。
* Dameng driver.
*
* @package framework
*/
class dm extends dao
{
/**
* 设置$table属性。
* Set the $table property.
*
* @param string $table
* @access public
* @return void
*/
public function setTable($table)
{
$this->table = trim($table, '`');
}
/**
* Show tables.
*
* @access public
* @return array
*/
public function showTables()
{
$sql = "SELECT \"table_name\" FROM all_tables WHERE OWNER = '{$this->config->db->name}'";
return $this->query($sql)->fetchAll(PDO::FETCH_ASSOC);
}
/**
* Get table engines.
*
* @access public
* @return array
*/
public function getTableEngines()
{
$tables = $this->query("SELECT \"table_name\" FROM all_tables WHERE OWNER = '{$this->config->db->name}'")->fetchAll();
$tableEngines = array();
foreach($tables as $table) $tableEngines[$table->table_name] = 'InnoDB';
return $tableEngines;
}
/**
* 类MySQL的DESC语法。
* Desc table, show fields.
*
* @param string $tableName
* @access public
* @return array
*/
public function descTable($tableName)
{
$tableName = trim($tableName, '`');
$this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
$sql = "select * from all_tab_columns where table_name = '$tableName'";
$rawFields = $this->dbh->query($sql)->fetchAll();
$this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
$fields = array();
foreach($rawFields as $rawField)
{
$field = new stdClass();
$field->field = $rawField->column_name;
$field->type = $rawField->data_type;
$field->null = $rawField->nullable;
$fields[] = $field;
}
return $fields;
}
/**
* select方法,调用sql::select()。
* The select method, call sql::select().
*
* @param string $fields
* @access public
* @return static|sql|baseDAO the dao object self.
*/
public function select($fields = '*')
{
/* Split by ','. */
$fieldList = preg_split("/,(?![^(]+\))/", $fields);
foreach($fieldList as $key => $field)
{
$field = trim($field);
$pos = strrpos($field, ' ');
if($pos)
{
$originField = substr($field, 0, $pos);
$alias = trim(substr($field, $pos));
$fieldList[$key] = $this->formatField($originField, $alias);
}
else
{
$fieldList[$key] = $this->formatField($field);
}
}
return parent::select(implode(',', $fieldList));
}
/**
* Format field: date => "date", t1.date => t1."date"
*
* @param string $originField
* @param string $alias
* @access private
* @return tring
*/
private function formatField($originField, $alias = '')
{
/* Format originField. */
$replace = array(
'GROUP_CONCAT' => 'WM_CONCAT',
);
if(stripos($originField, 'if(') !== false)
{
$originField = $this->dbh->formatDmIfFunction($originField);
}
elseif(strcasecmp($originField, 'distinct') !== 0)
{
$tableField = explode('.', $originField);
if(count($tableField) == 2 and ctype_alnum($tableField[1]) and $tableField[1] != '*')
{
$originField = $tableField[0] . '."' . $tableField[1] . '"';
}
elseif(count($tableField) == 1 and ctype_alnum($tableField[0]) and $tableField[0] != '*')
{
$originField = '"' . $tableField[0] . '"';
}
$originField = str_ireplace(array_keys($replace), array_values($replace), $originField);
}
/* Format alias. */
if($alias and !is_numeric($alias) and ctype_alnum($alias)) $alias = '"' . $alias . '"';
return $originField . ' ' . $alias;
}
/**
* Format if function.
*
* @param string $field
* @access private
* @return string
*/
/*
private function formatIfFunction($field)
{
preg_match('/if\(.+\)+/i', $field, $matches);
$if = $matches[0];
if(substr_count($if, '(') == 1)
{
$pos = strpos($if, ')');
$if = substr($if, 0, $pos+1);
}
// * fix sum(if(..., 1, 0)) , count(if(..., 1, 0)) * //
if(substr($if, strlen($if)-2) == '))' and (stripos($field, 'sum(') == 0 or stripos($field, 'count(') == 0)) $if = substr($if, 0, strlen($if)-1);
$parts = explode(',', substr($if, 3, strlen($if)-4)); // remove 'if(' and ')'
$case = 'CASE WHEN ' . implode(',', array_slice($parts, 0, count($parts)-2)) . ' THEN ' . $parts[count($parts)-2] . ' ELSE ' . $parts[count($parts)-1] . ' END';
$field = str_ireplace($if, $case, $field);
return $field;
}
*/
/**
* 创建WHERE部分。
* Create the where part.
*
* @param string $arg1 the field name
* @param string $arg2 the operator
* @param string $arg3 the value
* @access public
* @return static|sql the sql object.
*/
public function where($arg1 = '', $arg2 = null, $arg3 = null)
{
$arg1 = $this->formatWhere($arg1);
return parent::where($arg1, $arg2, $arg3);
}
/**
* 创建AND部分。
* Create the AND part.
*
* @param string $condition
* @access public
* @return static|sql the sql object.
*/
public function andWhere($condition = '', $addMark = false)
{
$condition = $this->formatWhere($condition);
return parent::andWhere($condition, $addMark);
}
/**
* 创建OR部分。
* Create the OR part.
*
* @param bool $condition
* @access public
* @return static|sql the sql object.
*/
public function orWhere($condition)
{
$condition = $this->formatWhere($condition);
return parent::orWhere($condition);
}
private function formatWhere($condition)
{
$condition = trim($condition);
if($condition == '1') return '1 = 1';
$pos = strrpos($condition, ' ');
if($pos)
{
$originField = substr($condition, 0, $pos);
return $this->formatField($originField) . substr($condition, $pos);
}
else
{
return $this->formatField($condition);
}
}
/**
* 创建GROUP BY部分。
* Create the groupby part.
*
* @param string $groupBy
* @access public
* @return static|sql the sql object.
*/
public function groupBy($groupBy)
{
$groups = preg_split("/,(?![^(]+\))/", $groupBy);
foreach($groups as $key => $group)
{
$groups[$key] = $this->formatField($group);
}
$groupBy = implode(',', $groups);
return parent::groupBy($groupBy);
}
/**
* 创建ORDER BY部分。
* Create the order by part.
*
* @param string $order
* @access public
* @return static|sql the sql object.
*/
public function orderBy($order)
{
$order = str_replace('"', '', $order);
return parent::orderBy($order);
}
/**
* 创建ON部分。
* Create the on part.
*
* @param string $condition
* @access public
* @return static|sql the sql object.
*/
public function on($condition)
{
$fieldList = explode('=', $condition);
foreach($fieldList as $key => $field) $fieldList[$key] = $this->formatField(trim($field));
$condition = implode(' = ', $fieldList);
return parent::on($condition);
}
/**
* 获取唯一索引的列。
* Get unique columns.
*
* @access public
* @return array
*/
public function getUniqueColumns()
{
$sql = "SELECT * from dba_ind_columns WHERE index_owner = '{$this->config->db->name}' AND index_name IN (SELECT index_name FROM dba_indexes WHERE table_name='{$this->table}' AND INDEX_TYPE = 'NORMAL' AND UNIQUENESS = 'UNIQUE' AND INDEX_NAME NOT IN (SELECT INDEX_NAME FROM DBA_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'P'))";
$columns = $this->dbh->query($sql)->fetchAll();
$cols = array();
foreach($columns as $col) $cols[$col->COLUMN_NAME] = $col;
return $cols;
}
/**
* 执行SQL。query()会返回stmt对象,该方法只返回更改或删除的记录数。
* Execute the sql. It's different with query(), which return the stmt object. But this not.
*
* @param string $sql
* @access public
* @return int the modified or deleted records. 更改或删除的记录数。
*/
public function exec($sql = '')
{
if(!empty(dao::$errors)) return new PDOStatement(); // If any error, return an empty statement object to make sure the remain method to execute.
if($sql)
{
$this->sqlobj = new sql();
$this->sqlobj->sql = $sql;
}
else
{
$sql = $this->processSQL();
$this->sqlobj->sql = $sql;
}
if($this->method == 'replace' && !empty($this->sqlobj->data))
{
$insertSql = "INSERT INTO \"{$this->table}\" ";
$fields = '(';
$values = 'VALUES(';
foreach($this->sqlobj->data as $field => $value)
{
$fields .= "`{$field}`,";
if(is_string($value) or $value === null) $value = $this->sqlobj->quote($value);
$values .= $value . ',';
}
$fields = substr($fields, 0, -1);
$values = substr($values, 0, -1);
$fields .= ')';
$values .= ')';
$insertSql .= $fields . ' ' . $values;
$updateSql = str_replace('REPLACE', 'UPDATE', $sql);
$cols = $this->getUniqueColumns();
/* No unique keys, no replace. */
if(empty($cols)) return false;
$conditions = array();
foreach($cols as $colName => $col)
{
if(isset($this->sqlobj->data->{$colName})) $conditions[] = " \"{$colName}\" = '{$this->sqlobj->data->{$colName}}'";
}
if(!empty($conditions)) $updateSql .= ' WHERE ' . implode(' AND ', $conditions);
$deleteSql = "DELETE FROM \"{$this->table}\" WHERE ";
$ingore = array();
$ingore['`zt_config`'] = array('value');
foreach($this->sqlobj->data as $field => $value)
{
if(isset($ingore[$this->table]) and in_array($field, $ingore[$this->table])) continue;
if(!isset($cols[$field])) continue;
$deleteSql .= "`{$field}` = ";
$deleteSql .= is_string($value) ? "'{$value}'" : $value;
$deleteSql .= ' AND ';
}
$deleteSql = rtrim($deleteSql, 'AND ');
$sql = <<<EOT
DECLARE
E_IDENTITY_INSERT EXCEPTION;
E_INSTALL_DUP_VAL_ON_INDEX EXCEPTION;
E_UPDATE_DUP_VAL_ON_INDEX EXCEPTION;
PRAGMA EXCEPTION_INIT (E_IDENTITY_INSERT, -2723);
PRAGMA EXCEPTION_INIT (E_INSTALL_DUP_VAL_ON_INDEX, -6602);
PRAGMA EXCEPTION_INIT (E_UPDATE_DUP_VAL_ON_INDEX, -6610);
BEGIN
BEGIN
$insertSql;
EXCEPTION
WHEN DUP_VAL_ON_INDEX OR E_IDENTITY_INSERT THEN
$updateSql;
WHEN E_INSTALL_DUP_VAL_ON_INDEX THEN
$updateSql;
END;
EXCEPTION
WHEN E_UPDATE_DUP_VAL_ON_INDEX THEN
$deleteSql;
$insertSql;
END;
EOT;
self::$querys[] = $sql;
}
$sql = str_replace('`', '"', $sql);
try
{
if($this->table) unset(dao::$cache[$this->table]);
$this->reset();
return $this->dbh->exec($sql);
}
catch (PDOException $e)
{
$this->sqlError($e);
}
}
/**
* 获取一个记录。
* Fetch one record.
*
* @param string $field 如果已经设置获取的字段,则只返回这个字段的值,否则返回这个记录。
* if the field is set, only return the value of this field, else return this record
* @access public
* @return object|mixed
*/
public function fetch($field = '')
{
return parent::fetch($field);
}
/**
* 获取所有记录。
* Fetch all records.
*
* @param string $keyField 返回以该字段做键的记录
* the key field, thus the return records is keyed by this field
* @access public
* @return array the records
*/
public function fetchAll($keyField = '')
{
return parent::fetchAll($keyField);
}
/**
* 获取表的字段类型。
* Get the defination of fields of the table.
*
* @access public
* @return array
*/
public function getFieldsType()
{
try
{
$this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
$sql = "select * from all_tab_columns where table_name='{$this->table}'";
$rawFields = $this->dbh->rawQuery($sql)->fetchAll();
$this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
}
catch (PDOException $e)
{
$this->sqlError($e);
}
$fields = array();
foreach($rawFields as $rawField)
{
$firstPOS = strpos($rawField->data_type, '(');
$type = substr($rawField->data_type, 0, $firstPOS > 0 ? $firstPOS : strlen($rawField->data_type));
$type = str_replace(array('big', 'small', 'medium', 'tiny', 'var'), '', $type);
$field = array();
if($type == 'VARCHAR' or $type == 'CHAR')
{
$length = $rawField->data_length;
$field['rule'] = 'length';
$field['options']['max'] = $length;
$field['options']['min'] = 0;
}
elseif($type == 'INTEGER')
{
$field['rule'] = 'int';
}
elseif($type == 'FLOAT' or $type == 'DOUBLE')
{
$field['rule'] = 'float';
}
elseif($type == 'DATE')
{
$field['rule'] = 'date';
}
elseif($type == 'DATETIME')
{
$field['rule'] = 'datetime';
}
else
{
$field['rule'] = 'skip';
}
$fields[$rawField->column_name] = $field;
}
return $fields;
}
}
+1 -1
View File
@@ -45,7 +45,7 @@ class dbh
*/
public function __construct($config, $setSchema = true)
{
$dsn = "{$config->driver}:host={$config->host}:{$config->port}";
$dsn = "{$config->driver}:host={$config->host};port={$config->port}";
if($setSchema) $dsn .= ";dbname={$config->name}";
$pdo = new PDO($dsn, $config->user, $config->password);
+8 -7
View File
@@ -1161,9 +1161,7 @@ class actionModel extends model
->beginIF($account != 'all')->andWhere('actor')->eq($account)->fi()
->beginIF($beginDate)->andWhere('date')->ge($beginDate)->fi()
->beginIF(is_numeric($productID))->andWhere('product')->like("%,$productID,%")->fi()
->andWhere()
->markLeft(1)
->where('1=1')
->andWhere('1=1', true)
->beginIF(is_numeric($projectID))->andWhere('project')->eq($projectID)->fi()
->beginIF(!empty($executions))->andWhere('execution')->in(array_keys($executions))->fi()
->beginIF(is_numeric($executionID))->andWhere('execution')->eq($executionID)->fi()
@@ -1975,10 +1973,7 @@ class actionModel extends model
if($case->scene)
{
$scene = $this->dao->select('*')->from(VIEW_SCENECASE)->where('id')->eq($case->scene)->fetch();
if($scene->deleted)
{
return print(js::error($this->lang->action->refusecase));
}
if($scene->deleted) return print(js::error($this->lang->action->refusecase));
}
}
@@ -1992,6 +1987,12 @@ class actionModel extends model
}
}
if($action->objectType == 'doc')
{
$docContent = $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->eq($action->objectID)->orderBy('version desc')->limit(1)->fetch();
if($docContent->files) $this->dao->update(TABLE_FILE)->set('deleted')->eq('0')->where('id')->in($docContent->files)->exec();
}
/* Update deleted field in object table. */
$table = $this->config->objectTables[$action->objectType];
$this->dao->update($table)->set('deleted')->eq(0)->where('id')->eq($action->objectID)->exec();
+1 -1
View File
@@ -478,7 +478,7 @@ class admin extends control
$response['thisTable'] = '';
$response['nextTable'] = '';
$tableEngines = $this->loadModel('misc')->getTableEngines();
$tableEngines = $this->dao->getTableEngines();
$thisTable = '';
$nextTable = '';
+1 -1
View File
@@ -12,5 +12,5 @@ $(function()
*/
function changeWeakChange(changeWeak)
{
$('#mainContent .table td.notice').html(changeWeak == 1 ? adminLang.safe.noticeWeakMode : adminLang.safe.noticeMode);
$('#mainContent .table td.notice:first').html(changeWeak == 1 ? adminLang.safe.noticeWeakMode : adminLang.safe.noticeMode);
}
+31 -11
View File
@@ -52,6 +52,15 @@ class api extends control
$objectType = $this->objectType;
$objectID = $this->objectID;
$isFirstLoad = $libID ? false : true;
if($libID)
{
$lib = $this->doc->getLibById($libID);
if($objectType == 'nolink' and !$objectID and ($lib->product or $lib->project))
{
$objectType = $lib->product ? 'product' : 'project';
$objectID = $lib->product ? $lib->product : $lib->project;
}
}
if($release)
{
@@ -158,7 +167,7 @@ class api extends control
if(!strpos($this->server->http_referer, 'space') and !strpos($this->server->http_referer, 'api')) setCookie("docSpaceParam", '', $this->config->cookieLife, $this->config->webRoot, '', false, true);
/* Get all api doc libraries. */
$libs = $this->doc->getApiLibs($libID);
$libs = $this->doc->getApiLibs($libID, $this->objectType, $this->objectID);
$api = $this->api->getLibById($apiID, $version, $release);
if($api)
{
@@ -174,7 +183,7 @@ class api extends control
}
/* Crumbs links array. */
$lib = zget($libs, $libID);
$lib = zget($libs, $libID);
$type = $lib->product ? 'product' : ($lib->project ? 'project' : 'unlink');
$methodName = $type != 'unlink' ? $type . 'Space' : 'index';
@@ -609,10 +618,11 @@ class api extends control
*
* @param int $libID
* @param int $moduleID
* @param string $space api|project|product
* @access public
* @return void
*/
public function create($libID, $moduleID = 0)
public function create($libID, $moduleID = 0, $space = '')
{
if(!empty($_POST))
{
@@ -621,14 +631,14 @@ class api extends control
$this->action->create('api', $api->id, 'Created');
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => 'true', 'callback' => "parentLocate({$api->id})"));
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => 'true', 'callback' => "parentLocate({$api->id}, {$api->lib}, {$api->module})"));
return $this->sendSuccess(array('locate' => helper::createLink('api', 'index', "libID={$api->lib}&moduleID={$api->module}&apiID={$api->id}")));
}
$libs = $this->doc->getLibs('api', '', $libID);
if(!$libID and !empty($libs)) $libID = key($libs);
$this->setMenu($libID);
$this->setMenu($libID, $space);
$lib = $this->doc->getLibByID($libID);
$libName = isset($lib->name) ? $lib->name . $this->lang->colon : '';
@@ -748,12 +758,14 @@ class api extends control
/**
* Set api menu by method name.
*
* @param int $libID
* @param int $libID
* @param string $space |null|api|project|product
* @access public
* @return void
*/
private function setMenu($libID = 0)
private function setMenu($libID = 0, $space = '')
{
if($space and strpos('|api|project|product|', "|{$space}|") === false) $space = '';
common::setMenuVars('doc', '');
$lib = $this->loadModel('doc')->getLibByID($libID);
@@ -766,14 +778,22 @@ class api extends control
$this->loadModel('project')->setMenu($lib->project);
}
if(in_array($this->session->spaceType, array('product', 'project')))
$spaceType = $this->session->spaceType;
if(empty($spaceType)) $spaceType = 'api';
if($space)
{
$this->lang->doc->menu->api['exclude'] = 'api-' . $this->app->rawMethod;
$this->lang->doc->menu->{$this->session->spaceType}['subModule'] = 'api';
$spaceType = $space;
$this->session->set('spaceType', $space, 'doc');
}
if(in_array($spaceType, array('product', 'project')))
{
$this->lang->doc->menu->api['exclude'] = 'api-' . $this->app->rawMethod . ',' . $this->app->rawMethod;
$this->lang->doc->menu->{$spaceType}['subModule'] = 'api';
}
else
{
$this->lang->doc->menu->{$this->session->spaceType}['alias'] .= ',' . $this->app->rawMethod;
$this->lang->doc->menu->{$spaceType}['alias'] .= ',' . $this->app->rawMethod;
}
}
+11
View File
@@ -1,3 +1,14 @@
.drop-body::-webkit-scrollbar,
#diffContain > .main-content::-webkit-scrollbar,
#content .detail-content.article-content::-webkit-scrollbar,
#outlineMenu::-webkit-scrollbar,
#history::-webkit-scrollbar {height: 0px; width: 0px; background: transparent;}
#diffContain > .main-content::-moz-scrollbar,
#content .detail-content.article-content::-moz-scrollbar,
#outlineMenu::-moz-scrollbar,
.drop-body::-moz-scrollbar,
#hostory::-moz-scrollbar {height: 0px; width: 0px; background: transparent;}
.split-row > .side-col,
.split-row > .main-col {padding: 0;}
.col-spliter {width: 20px; position: relative; z-index: 10; cursor: ew-resize;}
+4 -2
View File
@@ -92,9 +92,11 @@ var app = new Vue({
* @access public
* @return void
*/
function parentLocate(apiID)
function parentLocate(apiID, libID, moduelID)
{
libID = libID ? libID : 0;
moduelID = moduelID ? moduelID : 0;
config.onlybody = 'no';
var link = createLink('api', 'index', 'libID=0&moduleID=0&apiID=' + apiID) + '#app=doc';
var link = createLink('api', 'index', 'libID=' + libID + '&moduleID=' + moduelID + '&apiID=' + apiID) + '#app=doc';
window.parent.$.apps.open(link);
}
-2
View File
@@ -781,8 +781,6 @@ class apiModel extends model
$lib->baseUrl = $baseUrl;
$lib->acl = 'open';
$lib->users = ',' . $currentAccount . ',';
$lib->addedBy = $currentAccount;
$lib->addedDate = helper::now();
$this->dao->insert(TABLE_DOCLIB)->data($lib)->autoCheck()
->batchCheck($this->config->api->createlib->requiredFields, 'notempty')
->check('name', 'unique', "`type` = 'api'")
+1 -1
View File
@@ -115,7 +115,7 @@
<?php foreach($apiList as $api):?>
<li class="list-group-item">
<div class="heading <?php echo $api->method;?>">
<a href="<?php echo helper::createLink('api', 'index', "libID={$api->lib}&moduleID=0&apiID={$api->id}&version=0&release=$release");?>" data-app="<?php echo $app->tab;?>">
<a href="<?php echo helper::createLink('api', 'index', "libID={$api->lib}&moduleID=0&apiID={$api->id}&version=0");?>" data-app="<?php echo $app->tab;?>">
<span class="label label-primary"><?php echo $api->method;?></span>
<span class="path" title="<?php echo $api->path;?>"><?php echo $api->path;?></span>
<span class="desc" title="<?php echo $api->title;?>"><?php echo $api->title;?></span>
+4 -4
View File
@@ -10,12 +10,12 @@
<div class="version">
<div class='btn-group'>
<a href='javascript:;' class='btn btn-link btn-limit text-ellipsis' data-toggle='dropdown' style="max-width: 120px;">
#<?php echo $version ? $version : $api->version;?>
V<?php echo $version ? $version : $api->version;?>
<span class="caret"></span>
</a>
<ul class='dropdown-menu api-version-menu' style='max-height:240px; max-width: 300px; overflow-y:auto'>
<?php for($version = $api->version; $version > 0; $version--):?>
<li><a href='javascript:void(0)' data-url='<?php echo $this->createLink('api', 'index', "libID={$api->lib}&moduleID=0&apiID=$apiID&version=$version&release=$release");?>'>#<?php echo $version;?></a></li>
<ul class='dropdown-menu api-version-menu menu-active-primary menu-hover-primary' style='max-height:240px; max-width: 300px; overflow-y:auto'>
<?php for($itemVersion = $api->version; $itemVersion > 0; $itemVersion--):?>
<li <?php if($version == $itemVersion) echo 'class=active';?> ><a href='javascript:void(0)' data-url='<?php echo $this->createLink('api', 'index', "libID={$api->lib}&moduleID=0&apiID=$apiID&version=$itemVersion&release=$release");?>'>V<?php echo $itemVersion;?></a></li>
<?php endfor;?>
</ul>
</div>
+1 -1
View File
@@ -775,7 +775,7 @@ class blockModel extends model
$params = $this->appendCountParams();
$params->type['name'] = $this->lang->block->type;
$params->type['options'] = $this->lang->issue->labelList;
$params->type['options'] = $this->lang->issue->typeList;
$params->type['control'] = 'select';
$params->orderBy['name'] = $this->lang->block->orderBy;
+19 -6
View File
@@ -61,6 +61,8 @@ html[lang="de"] .block-productdoc .c-user{width: 105px;}
.block-productdoc .table .c-title > .draft {background-color:rgba(129, 102, 238, 0.12); color:#8166EE;}
</style>
<?php $blockNavId = 'nav-' . uniqid(); ?>
<?php js::set('emptyProducts', empty($products));?>
<?php js::set('emptyInvolveds', empty($involveds));?>
<script>
$(function()
{
@@ -90,6 +92,18 @@ function switch<?php echo "block{$block->id}";?>Product(obj)
function change<?php echo "block{$block->id}";?>ProductType(type)
{
var hiddenData = type == 'all' ? emptyProducts : emptyInvolveds;
if(hiddenData)
{
$('.block-productdoc<?php echo "#block{$block->id}";?> .dataBlock').addClass('hidden');
$('.block-productdoc<?php echo "#block{$block->id}";?> .block-statistic > .table-empty-tip').removeClass('hidden');
}
else
{
$('.block-productdoc<?php echo "#block{$block->id}";?> .dataBlock').removeClass('hidden');
$('.block-productdoc<?php echo "#block{$block->id}";?> .block-statistic > .table-empty-tip').addClass('hidden');
}
$('.block-productdoc<?php echo "#block{$block->id}";?> .nav.products').toggleClass('hidden', type != 'all');
$('.block-productdoc<?php echo "#block{$block->id}";?> .nav.involveds').toggleClass('hidden', type != 'involved');
$('.block-productdoc<?php echo "#block{$block->id}";?> #productType .btn').html($('.block-productdoc<?php echo "#block{$block->id}";?> #productType [data-type=' + type + ']').html() + " <span class='caret'></span>");
@@ -112,14 +126,14 @@ function change<?php echo "block{$block->id}";?>ProductType(type)
<li><a href="javascript:change<?php echo "block{$block->id}";?>ProductType('all')" data-type='all'><?php echo $lang->product->all;?></a></li>
</ul>
</div>
<?php $hiddenBlock = empty($involveds) ? 'hidden' : '';?>
<?php $hiddenEmpty = empty($involveds) ? '' : 'hidden';?>
<div class="panel-body">
<div class="table-row block-statistic">
<?php if(empty($products) and empty($involveds)):?>
<div class="table-empty-tip">
<div class="table-empty-tip <?php echo $hiddenEmpty;?>">
<p><span class="text-muted"><?php echo $lang->block->emptyTip;?></span></p>
</div>
<?php else:?>
<div class="col col-nav">
<div class="col col-nav dataBlock <?php echo $hiddenBlock;?>">
<ul class="nav nav-stacked nav-secondary scrollbar-hover involveds">
<li class='switch-icon prev'><a href='###' onclick='switch<?php echo "block{$block->id}";?>Product(this)'><i class='icon icon-arrow-left'></i></a></li>
<?php $selected = key($involveds);?>
@@ -142,7 +156,7 @@ function change<?php echo "block{$block->id}";?>ProductType(type)
<li class='switch-icon next'><a href='###' onclick='switch<?php echo "block{$block->id}";?>Product(this)'><i class='icon icon-arrow-right'></i></a></li>
</ul>
</div>
<div class="col tab-content">
<div class="col tab-content dataBlock <?php echo $hiddenBlock;?>">
<?php foreach($products as $product):?>
<div class="tab-pane fade<?php if($product->id == $selected) echo ' active in';?>" id='<?php echo "tab3{$blockNavId}Content{$product->id}";?>'>
<?php if(isset($docGroup[$product->id])):?>
@@ -190,6 +204,5 @@ function change<?php echo "block{$block->id}";?>ProductType(type)
</div>
<?php endforeach;?>
</div>
<?php endif;?>
</div>
</div>
+20 -7
View File
@@ -60,8 +60,10 @@ html[lang="de"] .block-projectdoc .c-user{width: 105px;}
.block-projectdoc .table .c-title[data-status=draft] > .doc-title {max-width: calc(100% - 35px);}
.block-projectdoc .table .c-title > .draft {background-color:rgba(129, 102, 238, 0.12); color:#8166EE;}
</style>
<?php $blockNavId = 'nav-' . uniqid();?>
<?php js::set('emptyProjects', empty($projects));?>
<?php js::set('emptyInvolveds', empty($involveds));?>
<script>
<?php $blockNavId = 'nav-' . uniqid(); ?>
$(function()
{
if($('.block-projectdoc<?php echo "#block{$block->id}";?> #projectType').length > 1);
@@ -90,6 +92,18 @@ function switch<?php echo "block{$block->id}";?>Project(obj)
function change<?php echo "block{$block->id}";?>ProjectType(type)
{
var hiddenData = type == 'all' ? emptyProjects : emptyInvolveds;
if(hiddenData)
{
$('.block-projectdoc<?php echo "#block{$block->id}";?> .dataBlock').addClass('hidden');
$('.block-projectdoc<?php echo "#block{$block->id}";?> .block-statistic > .table-empty-tip').removeClass('hidden');
}
else
{
$('.block-projectdoc<?php echo "#block{$block->id}";?> .dataBlock').removeClass('hidden');
$('.block-projectdoc<?php echo "#block{$block->id}";?> .block-statistic > .table-empty-tip').addClass('hidden');
}
$('.block-projectdoc<?php echo "#block{$block->id}";?> .nav.projects').toggleClass('hidden', type != 'all');
$('.block-projectdoc<?php echo "#block{$block->id}";?> .nav.involveds').toggleClass('hidden', type != 'involved');
$('.block-projectdoc<?php echo "#block{$block->id}";?> #projectType .btn').html($('.block-projectdoc<?php echo "#block{$block->id}";?> #projectType [data-type=' + type + ']').html() + " <span class='caret'></span>");
@@ -112,14 +126,14 @@ function change<?php echo "block{$block->id}";?>ProjectType(type)
<li><a href="javascript:change<?php echo "block{$block->id}";?>ProjectType('all')" data-type='all'><?php echo $lang->project->all;?></a></li>
</ul>
</div>
<?php $hiddenBlock = empty($involveds) ? 'hidden' : '';?>
<?php $hiddenEmpty = empty($involveds) ? '' : 'hidden';?>
<div class="panel-body">
<div class="table-row block-statistic">
<?php if(empty($projects) and empty($involveds)):?>
<div class="table-empty-tip">
<div class="table-empty-tip <?php echo $hiddenEmpty;?>">
<p><span class="text-muted"><?php echo $lang->block->emptyTip;?></span></p>
</div>
<?php else:?>
<div class="col col-nav">
<div class="col col-nav dataBlock <?php echo $hiddenBlock;?>">
<ul class="nav nav-stacked nav-secondary scrollbar-hover involveds">
<li class='switch-icon prev'><a href='###' onclick='switch<?php echo "block{$block->id}";?>Project(this)'><i class='icon icon-arrow-left'></i></a></li>
<?php $selected = key($involveds);?>
@@ -142,7 +156,7 @@ function change<?php echo "block{$block->id}";?>ProjectType(type)
<li class='switch-icon next'><a href='###' onclick='switch<?php echo "block{$block->id}";?>Project(this)'><i class='icon icon-arrow-right'></i></a></li>
</ul>
</div>
<div class="col tab-content">
<div class="col tab-content dataBlock <?php echo $hiddenBlock;?>">
<?php foreach($projects as $project):?>
<div class="tab-pane fade<?php if($project->id == $selected) echo ' active in';?>" id='<?php echo "tab3{$blockNavId}Content{$project->id}";?>'>
<?php if(isset($docGroup[$project->id])):?>
@@ -190,6 +204,5 @@ function change<?php echo "block{$block->id}";?>ProjectType(type)
</div>
<?php endforeach;?>
</div>
<?php endif;?>
</div>
</div>
+1 -1
View File
@@ -84,7 +84,7 @@ function setLane(regionID, num)
*/
function loadExecutionBuilds(productID, executionID, index)
{
var branch = $('#branches' + index).val();
var branch = $('#branches' + index).val() ? $('#branches' + index).val() : 0;
if(executionID == 'ditto')
{
for(var i = index - 1; i > 0, executionID == 'ditto'; i--)
+2 -2
View File
@@ -254,7 +254,7 @@ class buildModel extends model
$buildIdList = str_replace('trunk', '0', $buildIdList);
$selectedBuilds = $this->dao->select('id, name')->from(TABLE_BUILD)
->where('id')->in($buildIdList)
->beginIF($products)->andWhere('product')->in($productIdList)->fi()
->beginIF($products and $products != 'all')->andWhere('product')->in($productIdList)->fi()
->beginIF($objectType === 'execution' and $objectID)->andWhere('execution')->eq($objectID)->fi()
->beginIF($objectType === 'project' and $objectID)->andWhere('project')->eq($objectID)->fi()
->beginIF(strpos($params, 'hasdeleted') === false)->andWhere('deleted')->eq(0)->fi()
@@ -274,7 +274,7 @@ class buildModel extends model
->beginIF(strpos($params, 'hasdeleted') === false)->andWhere('t1.deleted')->eq(0)->fi()
->beginIF(strpos($params, 'hasproject') !== false)->andWhere('t1.project')->ne(0)->fi()
->beginIF(strpos($params, 'singled') !== false)->andWhere('t1.execution')->ne(0)->fi()
->beginIF($products)->andWhere('t1.product')->in($productIdList)->fi()
->beginIF($products and $products != 'all')->andWhere('t1.product')->in($productIdList)->fi()
->beginIF($objectType === 'execution' and $objectID)->andWhere('t1.execution')->eq($objectID)->fi()
->beginIF($objectType === 'project' and $objectID)->andWhere('t1.project')->eq($objectID)->fi()
->orderBy('t1.date desc, t1.id desc')->fetchAll('id');
+1 -1
View File
@@ -183,7 +183,7 @@ class caselibModel extends model
$lib = fixer::input('post')
->stripTags($this->config->caselib->editor->create['id'], $this->config->allowedTags)
->setForce('type', 'library')
->setIF($this->lang->navGroup->caselib != 'qa', 'project', $this->session->project)
->setIF($this->lang->navGroup->caselib != 'qa', 'project', (int)$this->session->project)
->add('addedBy', $this->app->user->account)
->add('addedDate', helper::now())
->remove('uid')
+1 -1
View File
@@ -181,7 +181,7 @@ class chart extends control
$sql = str_replace(';', '', "$post->sql");
$fields = $post->fieldSettings;
$langs = isset($post->langs) ? $post->langs : array();
$langs = !empty($post->langs) ? $post->langs : array();
switch($type)
{
+4 -4
View File
@@ -36,7 +36,7 @@ $lang->chart->typeList = array();
$lang->chart->typeList['pie'] = 'Pie';
$lang->chart->typeList['line'] = 'Line';
$lang->chart->typeList['radar'] = 'Radar';
$lang->chart->typeList['cluBarY'] = 'clustered Bar Y';
$lang->chart->typeList['stackedBarY'] = 'stacked Bar Y';
$lang->chart->typeList['cluBarX'] = 'clustered Bar X';
$lang->chart->typeList['stackedBar'] = 'stacked Bar';
$lang->chart->typeList['cluBarY'] = 'Clustered Bar Y';
$lang->chart->typeList['stackedBarY'] = 'Stacked Bar Y';
$lang->chart->typeList['cluBarX'] = 'Clustered Bar X';
$lang->chart->typeList['stackedBar'] = 'Stacked Bar';
+4 -4
View File
@@ -36,7 +36,7 @@ $lang->chart->typeList = array();
$lang->chart->typeList['pie'] = 'Pie';
$lang->chart->typeList['line'] = 'Line';
$lang->chart->typeList['radar'] = 'Radar';
$lang->chart->typeList['cluBarY'] = 'clustered Bar Y';
$lang->chart->typeList['stackedBarY'] = 'stacked Bar Y';
$lang->chart->typeList['cluBarX'] = 'clustered Bar X';
$lang->chart->typeList['stackedBar'] = 'stacked Bar';
$lang->chart->typeList['cluBarY'] = 'Clustered Bar Y';
$lang->chart->typeList['stackedBarY'] = 'Stacked Bar Y';
$lang->chart->typeList['cluBarX'] = 'Clustered Bar X';
$lang->chart->typeList['stackedBar'] = 'Stacked Bar';
+4 -4
View File
@@ -36,7 +36,7 @@ $lang->chart->typeList = array();
$lang->chart->typeList['pie'] = 'Pie';
$lang->chart->typeList['line'] = 'Line';
$lang->chart->typeList['radar'] = 'Radar';
$lang->chart->typeList['cluBarY'] = 'clustered Bar Y';
$lang->chart->typeList['stackedBarY'] = 'stacked Bar Y';
$lang->chart->typeList['cluBarX'] = 'clustered Bar X';
$lang->chart->typeList['stackedBar'] = 'stacked Bar';
$lang->chart->typeList['cluBarY'] = 'Clustered Bar Y';
$lang->chart->typeList['stackedBarY'] = 'Stacked Bar Y';
$lang->chart->typeList['cluBarX'] = 'Clustered Bar X';
$lang->chart->typeList['stackedBar'] = 'Stacked Bar';
+121 -9
View File
@@ -54,6 +54,12 @@ class chartModel extends model
$chart->fieldSettings = array();
}
if(!empty($chart->settings) and $chart->settings != 'null')
{
$settings = json_decode($chart->settings, true);
if(isset($settings[0]) and isset($settings[0]['type'])) $chart->type = $settings[0]['type'];
}
if($chart->sql == null) $chart->sql = '';
if(!empty($chart->filters)) $chart->filters = json_decode($chart->filters, true);
@@ -72,7 +78,7 @@ class chartModel extends model
if(!empty($chart->sql)) $chart->sql = trim(str_replace(';', '', $chart->sql));
if(!empty($chart->settings)) $chart->settings = json_decode($chart->settings, true);
if(!empty($chart->settings) and is_array($chart->settings))
if(empty($chart->type) and !empty($chart->settings) and is_array($chart->settings))
{
$firstSetting = current($chart->settings);
if(isset($firstSetting['type'])) $chart->type = $firstSetting['type'];
@@ -396,7 +402,7 @@ class chartModel extends model
$optionList = $this->getSysOptions($fields[$group]['type'], $fields[$group]['object'], $fields[$group]['field']);
foreach($xLabels as $index => $xLabel) $xLabels[$index] = isset($optionList[$xLabel]) ? $optionList[$xLabel] : $xLabel;
$xaxis = array('type' => 'category', 'data' => $xLabels, 'boundaryGap' => false);
$xaxis = array('type' => 'category', 'data' => $xLabels, 'axisTick' => array('alignWithLabel' => true));
$yaxis = array('type' => 'value');
$legend = new stdclass();
$series = array();
@@ -456,7 +462,7 @@ class chartModel extends model
$optionList = $this->getSysOptions($fields[$group]['type'], $fields[$group]['object'], $fields[$group]['field']);
foreach($xLabels as $index => $xLabel) $xLabels[$index] = isset($optionList[$xLabel]) ? $optionList[$xLabel] : $xLabel;
$xaxis = array('type' => 'category', 'data' => $xLabels, 'axisLabel' => array('interval' => 0), 'boundaryGap' => false);
$xaxis = array('type' => 'category', 'data' => $xLabels, 'axisLabel' => array('interval' => 0), 'axisTick' => array('alignWithLabel' => true));
$yaxis = array('type' => 'value');
$legend = new stdclass();
@@ -615,17 +621,18 @@ class chartModel extends model
if($field)
{
$path = $this->app->getModuleRoot() . 'dataview' . DS . 'table' . DS . "$object.php";
if(!is_file($path)) return;
include $path;
$options = $schema->fields[$field]['options'];
if(is_file($path))
{
include $path;
$options = $schema->fields[$field]['options'];
}
}
break;
case 'object':
if($field)
{
$table = zget($this->config->objectTables, $object);
$options = $this->dao->select("id, {$field}")->from($table)->fetchPairs();
$table = zget($this->config->objectTables, $object, '');
if($table) $options = $this->dao->select("id, {$field}")->from($table)->fetchPairs();
}
break;
case 'string':
@@ -696,5 +703,110 @@ class chartModel extends model
return $filterFormat;
}
/**
* Get tables.
*
* @param string $sql
* @access public
* @return array
*/
public function getTables($sql)
{
$processedSql = trim($sql, ';');
$processedSql = str_replace(array("\r\n", "\n"), ' ', $processedSql);
$processedSql = str_replace('`', '', $processedSql);
preg_match_all('/^select (.+) from (.+)$/i', $processedSql, $selectAndFrom);
if(empty($selectAndFrom[2][0])) return false;
$selectSql = $selectAndFrom[1][0];
$tableSql = $fromSql = $selectAndFrom[2][0];
if(stripos($fromSql, 'where') !== false) $tableSql = trim(substr($fromSql, 0, stripos($fromSql, 'where')));
if(stripos($fromSql, 'limit') !== false) $tableSql = trim(substr($fromSql, 0, stripos($fromSql, 'limit')));
if(stripos($fromSql, 'having') !== false) $tableSql = trim(substr($fromSql, 0, stripos($fromSql, 'having')));
if(stripos($fromSql, 'group by') !== false) $tableSql = trim(substr($fromSql, 0, stripos($fromSql, 'group by')));
/* Remove such as "left join|right join|join", "on (t1.id=t2.id)", result like t1, t2 as t3. */
$tableSql .= ' ';
if(stripos($tableSql, 'join') !== false) $tableSql = preg_replace(array('/join\s+([A-Z]+_\w+ .*)on/Ui', '/,\s*on\s+[^,]+/i'), array(',$1,on', ''), $tableSql);
/* Match t2 as t3 */
preg_match_all('/(\w+) +as +(\w+)/i', $tableSql, $out);
$fields = explode(',', $selectSql);
foreach($fields as $i => $field)
{
if($field) $asField = '';
if(strrpos($field, ' as ') !== false) list($field, $asField) = explode(' as ', $field);
if(strrpos($field, ' AS ') !== false) list($field, $asField) = explode(' AS ', $field);
$field = trim($field);
$asField = trim($asField);
$fieldName = $field;
if(strrpos($field, '.') !== false)
{
$table = substr($field, 0, strrpos($field, '.'));
$fieldName = substr($field, strrpos($field, '.') + 1);
if(!empty($out[0]) and in_array($table, $out[2]))
{
$realTable = $out[1][array_search($table, $out[2])];
$tableFieldName = str_replace($table . '.', $realTable . '.', $field);
if(isset($fields[$fieldName]) && !$asField)
{
$fieldName = str_replace('.', '', $field);
$sql = preg_replace(array("/$field/", "/`$field`/"), array("$field AS $fieldName", "`$field` AS $fieldName"), $sql, 1);
$field = $tableFieldName;
}
}
if($fieldName == '*') $fieldName = $field;
}
$fieldName = $asField ? $asField : $fieldName;
$fields[$fieldName] = $field;
unset($fields[$i]);
}
$tableSql = preg_replace('/as +\w+/i', ' ', $tableSql);
$tableSql = trim(str_replace(array('(', ')', ','), ' ', $tableSql));
$tableSql = preg_replace('/ +/', ' ', $tableSql);
$tables = explode(' ', $tableSql);
return array('sql' => $sql, 'tables' => $tables, 'fields' => $fields);
}
/**
* Parse variables to null string in sql.
*
* @param string $sql
* @access public
* @return string
*/
public function parseSqlVars($sql, $filters)
{
if($filters)
{
foreach($filters as $filter)
{
if(!isset($filter['default'])) continue;
if(isset($filter['from']) and $filter['from'] == 'query')
{
$default = "'{$filter['default']}'";
$sql = str_replace('$' . $filter['field'], $default, $sql);
}
}
}
if(preg_match_all("/[\$]+[a-zA-Z0-9]+/", $sql, $out))
{
foreach($out[0] as $match) $sql = str_replace($match, "''", $sql);
}
return $sql;
}
}
+24 -22
View File
@@ -44,31 +44,33 @@
<div id="mainContent" class='main-row'>
<div class='side-col col-lg'>
<div class='panel'>
<div class='panel-heading'>
<div class='panel-title'><?php echo isset($group->name) ? $group->name : '';?></div>
</div>
<div class='panel-body'>
<?php if(!$chartTree):?>
<hr class="space">
<div class="text-center text-muted">
<?php echo $lang->chart->noChart;?>
<div class="cell">
<div class='panel'>
<div class='panel-heading text-ellipsis'>
<div class='panel-title'><?php echo isset($group->name) ? $group->name : '';?></div>
</div>
<hr class="space">
<?php elseif($chartTree):?>
<form method='post'>
<?php echo $chartTree;?>
<div class='btn-toolbar'>
<?php echo html::selectAll();?>
<?php echo html::submitButton($lang->chart->preview, '', 'btn btn-primary');?>
<div class='panel-body'>
<?php if(!$chartTree):?>
<hr class="space">
<div class="text-center text-muted">
<?php echo $lang->chart->noChart;?>
</div>
</form>
<?php endif;?>
<?php if($this->config->edition == 'open'):?>
<div class='text biz-version'>
<span class='text-important'><?php echo (!empty($config->isINT)) ? $lang->bizVersionINT : $lang->bizVersion;?></span>
<hr class="space">
<?php elseif($chartTree):?>
<form method='post'>
<?php echo $chartTree;?>
<div class='btn-toolbar'>
<?php echo html::selectAll();?>
<?php echo html::submitButton($lang->chart->preview, '', 'btn btn-primary');?>
</div>
</form>
<?php endif;?>
<?php if($this->config->edition == 'open'):?>
<div class='text biz-version'>
<span class='text-important'><?php echo (!empty($config->isINT)) ? $lang->bizVersionINT : $lang->bizVersion;?></span>
</div>
<?php endif;?>
</div>
<?php endif;?>
</div>
</div>
</div>
+3 -3
View File
@@ -256,7 +256,7 @@ $lang->waterfall->menu = new stdclass();
$lang->waterfall->menu->index = array('link' => "$lang->dashboard|project|index|project=%s");
$lang->waterfall->menu->execution = array('link' => "{$lang->stage->common}|project|execution|status=all&projectID=%s", 'subModule' => 'programplan,task');
$lang->waterfall->menu->storyGroup = array('link' => "{$lang->common->story}|projectstory|story|projectID=%s",'class' => 'dropdown dropdown-hover', 'exclude' => 'tree-browse,projectstory-track');
$lang->waterfall->menu->story = array('link' => "$lang->SRCommon|projectstory|story|projectID=%s", 'subModule' => 'projectstory,tree', 'alias' => 'story', 'exclude' => 'projectstory-track');
$lang->waterfall->menu->story = array('link' => "$lang->SRCommon|projectstory|story|projectID=%s", 'subModule' => 'projectstory,tree', 'alias' => 'story', 'exclude' => 'projectstory-track,tree-browse');
$lang->waterfall->menu->design = array('link' => "{$lang->design->common}|design|browse|project=%s");
$lang->waterfall->menu->qa = array('link' => "{$lang->qa->common}|project|bug|projectID=%s", 'subModule' => 'testcase,testtask,bug,testreport', 'alias' => 'bug,testtask,testcase,testreport');
$lang->waterfall->menu->doc = array('link' => "{$lang->doc->common}|doc|projectSpace|objectID=%s");
@@ -264,9 +264,9 @@ $lang->waterfall->menu->devops = array('link' => "{$lang->repo->common}|repo
$lang->waterfall->menu->build = array('link' => "{$lang->build->common}|projectbuild|browse|project=%s", 'subModule' => 'projectbuild');
$lang->waterfall->menu->release = array('link' => "{$lang->release->common}|projectrelease|browse|project=%s", 'subModule' => 'projectrelease');
$lang->waterfall->menu->dynamic = array('link' => "$lang->dynamic|project|dynamic|project=%s");
$lang->waterfall->menu->settings = array('link' => "$lang->settings|project|view|project=%s", 'subModule' => 'stakeholder', 'alias' => 'edit,manageproducts,group,managemembers,manageview,managepriv,whitelist,addwhitelist,team', 'exclude' => 'tree-browsetask');
$lang->waterfall->dividerMenu = ',programplan,build,dynamic,';
$lang->waterfall->menu->settings = $lang->scrum->menu->settings;
$lang->waterfall->dividerMenu = ',programplan,build,dynamic,';
$lang->waterfall->menu->storyGroup['dropMenu'] = $lang->scrum->menu->storyGroup['dropMenu'];
+2 -25
View File
@@ -1487,31 +1487,7 @@ class commonModel extends model
echo "<a href='javascript:;'>" . "<i class='icon icon-download'></i> " . $lang->clientName . "</a><ul class='dropdown-menu pull-left'>";
echo '<li>' . html::a(helper::createLink('misc', 'downloadClient', '', '', true), $lang->downloadClient, '', "title='$lang->downloadClient' class='iframe text-ellipsis' data-width='600'") . '</li>';
echo "<li class='dropdown-submenu' id='downloadMobile'><a href='javascript:;'>" . $lang->downloadMobile . "</a><ul class='dropdown-menu pull-left''>";
/* Intranet users use local pictures. */
$connected = false;
if(extension_loaded('curl'))
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://www.zentao.net/page/appqrcode.json');
curl_setopt($curl, CURLOPT_TIMEOUT_MS, 200);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT_MS, 200);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
$connected = curl_exec($curl);
curl_close($curl);
}
if($connected)
{
echo "<li><div class='mobile-qrcode'><iframe src='https://www.zentao.net/page/appqrcode.html?v={$config->version}' frameborder='0' scrolling='no' seamless></iframe></div></li>";
}
else
{
echo "<li><div class='mobile-qrcode local-img'><img src='{$config->webRoot}theme/default/images/main/mobile_qrcode.png' /><div class='mobile-version'><span>v1.2</span></div></li>";
}
echo "<li><div class='mobile-qrcode local-img'><img src='{$config->webRoot}static/images/app-qrcode.png' /></li>";
echo "</ul></li>";
echo '<li>' . html::a($lang->clientHelpLink, $lang->clientHelp, '', "title='$lang->clientHelp' target='_blank'") . '</li>';
echo '</ul></li>';
@@ -2078,6 +2054,7 @@ EOF;
if(strtolower($key) == 'assigneddate') continue;
if(strtolower($key) == 'editedby') continue;
if(strtolower($key) == 'editeddate') continue;
if(strtolower($key) == 'editingdate') continue;
if(strtolower($key) == 'uid') continue;
if(strtolower($key) == 'finisheddate' and $value == '') continue;
if(strtolower($key) == 'canceleddate' and $value == '') continue;
+7 -7
View File
@@ -128,7 +128,7 @@ class convertModel extends model
{
$dataList = $this->dao->dbh($this->sourceDBH)->select('t1.`ID`, t1.`lower_user_name` as account, t1.`lower_display_name` as realname, t1.`lower_email_address` as email, t1.created_date as `join`, t2.user_key as userCode')->from(JIRA_USERINFO)->alias('t1')
->leftJoin(JIRA_USER)->alias('t2')->on('t1.`lower_user_name` = t2.`lower_user_name`')
->where(1)
->where('1=1')
->beginIF($lastID)->andWhere('t1.ID')->gt($lastID)->fi()
->orderBy('t1.ID asc')->limit($limit)
->fetchAll('ID');
@@ -136,7 +136,7 @@ class convertModel extends model
elseif($module == 'project')
{
$dataList = $this->dao->dbh($this->sourceDBH)->select('*')->from(JIRA_PROJECT)
->where(1)
->where('1=1')
->beginIF($lastID)->andWhere('ID')->gt($lastID)->fi()
->orderBy('ID asc')->limit($limit)
->fetchAll('ID');
@@ -144,7 +144,7 @@ class convertModel extends model
elseif($module == 'issue')
{
$dataList = $this->dao->dbh($this->sourceDBH)->select('*')->from(JIRA_ISSUE)
->where(1)
->where('1=1')
->beginIF($lastID)->andWhere('ID')->gt($lastID)->fi()
->orderBy('ID asc')->limit($limit)
->fetchAll('ID');
@@ -152,7 +152,7 @@ class convertModel extends model
elseif($module == 'build')
{
$dataList = $this->dao->dbh($this->sourceDBH)->select('*')->from(JIRA_BUILD)
->where(1)
->where('1=1')
->beginIF($lastID)->andWhere('ID')->gt($lastID)->fi()
->orderBy('ID asc')->limit($limit)
->fetchAll('ID');
@@ -160,7 +160,7 @@ class convertModel extends model
elseif($module == 'issuelink')
{
$dataList = $this->dao->dbh($this->sourceDBH)->select('*')->from(JIRA_ISSUELINK)
->where(1)
->where('1=1')
->beginIF($lastID)->andWhere('ID')->gt($lastID)->fi()
->orderBy('ID asc')->limit($limit)
->fetchAll('ID');
@@ -168,7 +168,7 @@ class convertModel extends model
elseif($module == 'action')
{
$dataList = $this->dao->dbh($this->sourceDBH)->select('*')->from(JIRA_ACTION)
->where(1)
->where('1=1')
->beginIF($lastID)->andWhere('ID')->gt($lastID)->fi()
->orderBy('ID asc')->limit($limit)
->fetchAll('ID');
@@ -176,7 +176,7 @@ class convertModel extends model
elseif($module == 'file')
{
$dataList = $this->dao->dbh($this->sourceDBH)->select('*')->from(JIRA_FILE)
->where(1)
->where('1=1')
->beginIF($lastID)->andWhere('ID')->gt($lastID)->fi()
->orderBy('ID asc')->limit($limit)
->fetchAll('ID');
+11
View File
@@ -23,6 +23,17 @@ class dimensionModel extends model
return $this->dao->select('*')->from(TABLE_DIMENSION)->where('id')->eq($dimensionID)->fetch();
}
/**
* Get first dimension.
*
* @access public
* @return object
*/
public function getFirst()
{
return $this->dao->select('*')->from(TABLE_DIMENSION)->where('deleted')->eq('0')->orderBy('id')->limit(1)->fetch();
}
/**
* Get dimension list.
*
+5 -13
View File
@@ -603,7 +603,7 @@ class doc extends control
}
elseif($objectType == 'mine')
{
$this->lang->doc->aclList = $this->lang->doclib->mySpaceAclList['private'];
$this->lang->doc->aclList = $this->lang->doclib->mySpaceAclList;
}
$moduleOptionMenu = $this->doc->getLibsOptionMenu($libs);
@@ -650,16 +650,7 @@ class doc extends control
$this->doc->delete(TABLE_DOC, $docID);
/* Delete doc files. */
$this->loadModel('file');
foreach($doc->files as $fileID => $file)
{
$file = $this->file->getById($fileID);
$this->dao->delete()->from(TABLE_FILE)->where('id')->eq($fileID)->exec();
$this->loadModel('action')->create($file->objectType, $file->objectID, 'deletedFile', '', $extra=$file->title);
$fileRecord = $this->dao->select('id')->from(TABLE_FILE)->where('pathname')->eq($file->pathname)->fetch();
if(empty($fileRecord)) $this->file->unlinkFile($file);
}
if($doc->files) $this->dao->update(TABLE_FILE)->set('deleted')->eq('1')->where('id')->in(array_keys($doc->files))->exec();
/* if ajax request, send result. */
if($this->server->ajax)
@@ -1318,7 +1309,7 @@ class doc extends control
$this->view->libs = $libs;
$this->view->apiID = 0;
$this->view->release = 0;
$this->view->apiList = $browseType == 'bySearch' ? $this->api->getApiListBySearch($libID, $queryID, $type, array_keys($libs)) : $this->api->getListByModuleId($libID, $moduleID, 0, $pager);
$this->view->apiList = $browseType == 'bySearch' ? $this->api->getApiListBySearch($libID, $queryID, $type, array_keys($libs)) : $this->api->getListByModuleId($libID, $moduleID, $param, $pager);
}
else
{
@@ -1374,7 +1365,7 @@ class doc extends control
*/
public function productSpace($objectID = 0, $libID = 0, $moduleID = 0, $browseType = 'all', $orderBy = 'status,id_desc', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$products = $this->product->getPairs('nocode', 0, '', 'all');
$products = $this->product->getPairs('nocode');
$objectID = $this->product->saveState($objectID, $products);
echo $this->fetch('doc', 'tableContents', "type=product&objectID=$objectID&libID=$libID&moduleID=$moduleID&browseType=$browseType&orderBy=$orderBy&param=$param&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID");
@@ -1458,6 +1449,7 @@ class doc extends control
if(!common::hasPriv('doc', 'teamSpace')) unset($spaceList['custom']);
if(!common::hasPriv('api', 'index')) unset($spaceList['api']);
if(!common::hasPriv('api', 'create')) unset($spaceList['api'], $typeList['api']);
if($this->config->vision == 'lite') unset($spaceList['api'], $spaceList['product'], $typeList['api']);
$products = $this->loadModel('product')->getPairs();
$projects = $this->project->getPairsByProgram('', 'all', false, 'order_asc', 'kanban');
+17 -6
View File
@@ -1,15 +1,20 @@
.h-full-adjust {overflow-y: auto; height: calc(100vh - 125px);}
.main-col .block-files .panel-heading {padding-right: 20px;}
.main-col .block-files .panel-heading .panel-title {height: 35px; line-height: 30px;}
.main-col .doc-title {display: flex; font-size: 16px; margin-bottom: 10px; justify-content: space-between;}
/* css for page-title .*/
.main-col .doc-title {display: flex; font-size: 16px; margin-bottom: 10px; justify-content: space-between; width: 100%;}
.main-col .doc-title .info {flex: 0 0 60px;}
.main-col .doc-title #editorBox {flex: 0 0 190px;}
.main-col .doc-title .title {margin-right: 10px; line-height: 32px; font-size: 20px;}
.main-col .doc-title .info {flex: 1 1 0;}
.main-col .doc-title .version a {font-size: 13px; color: #8c8c8c;}
.main-col .doc-title .version .dropdown-menu a:hover {color: #ffffff;}
.main-col .doc-title .actions a + a {margin-left: 0px;}
.main-col .doc-title .actions {flex: 0 0 180px; display: flex;}
.main-col .doc-title .actions a + a {margin-left: 0px; flex: 0 0 32px;}
.main-col .doc-title .actions i {font-size: 15px; color: #8c8c8c;}
#content .title {max-width: 40%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
.main-col .doc-title .actions a > span {color: #9EA3B0;}
#content .title {overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
#mainContent .scrollbar-hover {max-height: 2000px; overflow: scroll;}
#content .editor-preview {background: #fff}
#content .CodeMirror{border: none}
@@ -24,10 +29,11 @@
.article-content .info {margin-bottom: 15px; width:100%; overflow:hidden;}
.article-content .info .user-time{margin-right: 4px}
.article-content .info .keywords .label {padding: 2px 8px; color:#18A6FD; border-color:rgba(24, 166, 253, 0.25); height: 18px; line-height:14px; margin-right:4px;}
.article-content {width: 100%; display: inline-block;}
.article-content img {margin: 0;}
.article-content.comment .comment-content {width: 94%;}
/* css for outlineMenu .*/
#outlineMenu {max-width: 200px; overflow-x: auto;}
#outlineMenu .tree li > a {text-overflow: clip;}
.outline-toggle i.icon-angle-right:before {content: "\e314"; cursor: pointer;}
@@ -71,12 +77,15 @@
#autoBox > .ellipsis {position: absolute; top: 3px; right: 0; width: 10px; background: #F4F5F7; height: 100%;}
.detail+.detail {padding-top: 0;}
.comment-edit-form .form-actions {display: flex;}
.drop-body::-webkit-scrollbar,
#diffContain > .main-content::-webkit-scrollbar,
#content .detail-content.article-content::-webkit-scrollbar,
#outlineMenu::-webkit-scrollbar,
#history::-webkit-scrollbar {height: 0px; width: 0px; background: transparent;}
#diffContain > .main-content::-moz-scrollbar,
#content .detail-content.article-content::-moz-scrollbar,
#outlineMenu::-moz-scrollbar,
.drop-body::-moz-scrollbar,
#hostory::-moz-scrollbar {height: 0px; width: 0px; background: transparent;}
.main-col iframe {min-height: unset;}
@@ -109,3 +118,5 @@
.exchangeDiffGroup.show-diff .right-dom {display: unset;}
.btn-limit {padding-left: 10px; padding-right: 20px;}
.tree li>.list-toggle {top: 5px; left: -4px;}
.flex-left {display: inline-flex; flex: auto}
+1 -1
View File
@@ -18,7 +18,7 @@ $(function()
$('#saveDraft').click(function()
{
if($('#editorTitle').val() == '')
if($.trim($('#editorTitle').val()) == '')
{
bootbox.alert(titleNotEmpty);
return false;
+1 -1
View File
@@ -8,7 +8,7 @@ $(function()
$('#saveDraft').click(function()
{
if($('#editorTitle').val() == '')
if($.trim($('#editorTitle').val()) == '')
{
bootbox.alert(titleNotEmpty);
return false;
+1 -1
View File
@@ -14,7 +14,7 @@ function redirectParentWindow(objectType, libID, moduleID, docType)
var link = '';
if(docType == 'api')
{
link = createLink('api', 'create', 'libID=' + libID + '&moduleID=' + moduleID);
link = createLink('api', 'create', 'libID=' + libID + '&moduleID=' + moduleID + '&space=' + objectType);
}
else
{
+19
View File
@@ -95,6 +95,7 @@ function fullScreen()
}
$('.main-col iframe').css('min-height', $(window).height() + 'px');
adjustPageTitleWidth();
}
/**
@@ -112,6 +113,20 @@ function exitFullScreen()
$('#content .detail').eq(1).removeClass('hidden');
$('.main-col iframe').css('min-height', '380px');
$.cookie('isFullScreen', 0);
adjustPageTitleWidth();
}
/**
* Adjust title width.
*
* @access public
* @return void
*/
function adjustPageTitleWidth()
{
var $titleContent = $('.detail-title.doc-title');
var titleWidth = $titleContent.width() - $titleContent.find('.info').width() - $titleContent.find('.actions').width() - $titleContent.find('#editorBox').width();
$titleContent.find('.flex-left > .title').css('max-width', titleWidth + 'px');
}
document.addEventListener('fullscreenchange', function (e)
@@ -188,10 +203,12 @@ $(function()
$history.addClass('hidden');
$icon.removeClass('text-primary');
}
adjustPageTitleWidth();
}).on('click', '#closeBtn', function()
{
$('#history').addClass('hidden');
$('#hisTrigger').removeClass('text-primary');
adjustPageTitleWidth();
});
$('#outline li.has-list').addClass('open in');
@@ -225,6 +242,7 @@ $(function()
}
$('#docExport').attr('href', createLink('doc', exportMethod, 'libID=' + libID + '&moduleID=0&docID=' + docID + '&version=' + $('#content .doc-title .version').data('version')));
if($('.files-list').length) $('#content .detail-content.article-content').css('height', 'calc(100vh - 300px)');
adjustPageTitleWidth();
});
})
@@ -233,4 +251,5 @@ $(function()
$('#history').find('.btn.pull-right').removeClass('pull-right');
if($('.files-list').length) $('#content .detail-content.article-content').css('height', 'calc(100vh - 300px)');
$('.outline .outline-toggle i.icon-menu-arrow-left').trigger("click");
adjustPageTitleWidth();
})
+55 -26
View File
@@ -47,13 +47,13 @@ class docModel extends model
$libs = $this->dao->select('*')->from(TABLE_DOCLIB)
->where('deleted')->eq(0)
->andWhere('type')->eq('api')
->beginIF(!empty($appendLib))->orWhere('id')->eq($appendLib)->fi()
->beginIF(!empty($objectType) && $objectID > 0 and $objectType != 'nolink')->andWhere($objectType)->eq($objectID)->fi()
->beginIF(!empty($objectType) and $objectID > 0 and $objectType != 'nolink')->andWhere($objectType)->eq($objectID)->fi()
->beginIF($objectType == 'nolink')
->andWhere('product')->eq(0)
->andWhere('project')->eq(0)
->andWhere('execution')->eq(0)
->fi()
->beginIF(!empty($appendLib))->orWhere('id')->eq($appendLib)->fi()
->orderBy('order_asc, id_asc')
->fetchAll('id');
@@ -101,7 +101,7 @@ class docModel extends model
$projects = $this->loadModel('project')->getPairsByProgram('', 'all', false, 'order_asc', $this->config->vision == 'rnd' ? 'kanban' : '');
$executions = $this->loadModel('execution')->getPairs(0, 'sprint,stage', 'multiple,leaf');
$waterfalls = array();
if(empty($objectID) and $type != 'product' and $type != 'project' and $type != 'custom')
if(empty($objectID) and $type == 'execution')
{
$waterfalls = $this->dao->select('t1.id,t2.name')->from(TABLE_EXECUTION)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
@@ -211,6 +211,8 @@ class docModel extends model
->remove('uid,contactListMenu,libType')
->get();
if(defined('IN_UPGRADE') and (($this->config->edition == 'open' and version_compare($this->config->version, '18.4.alpha1', '<')) or ($this->config->edition == 'biz' and version_compare($this->config->version, 'biz8.4.alpha1', '<')) or ($this->config->edition == 'max' and version_compare($this->config->version, 'max4.4.alpha1', '<')))) unset($lib->addedBy, $lib->addedDate);
if($lib->execution) $lib->type = 'execution';
if($lib->type == 'execution' and $lib->execution and !$lib->project)
{
@@ -253,6 +255,8 @@ class docModel extends model
->remove('uid,contactListMenu,libType')
->get();
if(defined('IN_UPGRADE') and (($this->config->edition == 'open' and version_compare($this->config->version, '18.4.alpha1', '<')) or ($this->config->edition == 'biz' and version_compare($this->config->version, 'biz8.4.alpha1', '<')) or ($this->config->edition == 'max' and version_compare($this->config->version, 'max4.4.alpha1', '<')))) unset($lib->addedBy, $lib->addedDate);
$this->app->loadLang('api');
/* Replace doc library name. */
@@ -382,15 +386,18 @@ class docModel extends model
*/
public function getDocsByBrowseType($browseType, $queryID, $moduleID, $sort, $pager)
{
$allLibs = $this->getLibs('all');
$allLibIDList = array_keys($allLibs);
$hasPrivDocIdList = $this->getPrivDocs(0, $moduleID);
if($browseType == "all")
if($browseType == 'all')
{
$docs = $this->getDocs(0, 0, $browseType, $sort, $pager);
}
elseif($browseType == 'bySearch')
else
{
$allLibs = $this->getLibs('all');
$allLibIDList = array_keys($allLibs);
$hasPrivDocIdList = $this->getPrivDocs($allLibIDList, $moduleID);
}
if($browseType == 'bySearch')
{
if($queryID)
{
@@ -437,7 +444,7 @@ class docModel extends model
$docs = $this->dao->select('t1.*, t2.name as libName, t2.type as objectType')->from(TABLE_DOC)->alias('t1')
->leftJoin(TABLE_DOCLIB)->alias('t2')->on("t1.lib=t2.id")
->where('t1.deleted')->eq(0)
->andWhere('t1.lib')->in($allLibIDList)
->andWhere('t1.lib')->ne('')
->andWhere('t1.id')->in($hasPrivDocIdList)
->beginIF($this->config->doc->notArticleType)->andWhere('t1.type')->notIN($this->config->doc->notArticleType)->fi()
->andWhere('t1.addedBy')->eq($this->app->user->account)
@@ -448,18 +455,18 @@ class docModel extends model
}
elseif($browseType == 'editedbyme')
{
$docIDList = $this->dao->select('objectID')->from(TABLE_ACTION)
$docIdList = $this->dao->select('objectID')->from(TABLE_ACTION)
->where('objectType')->eq('doc')
->andWhere('actor')->eq($this->app->user->account)
->andWhere('objectID')->in($hasPrivDocIdList)
->andWhere('action')->eq('edited')
->andWhere('vision')->eq($this->config->vision)
->fetchAll('objectID');
$docs = $this->dao->select('t1.*, t2.name as libName, t2.type as objectType')->from(TABLE_DOC)->alias('t1')
->leftJoin(TABLE_DOCLIB)->alias('t2')->on("t1.lib=t2.id")
->where('t1.deleted')->eq(0)
->andWhere('t1.id')->in(array_keys($docIDList))
->andWhere('t1.lib')->in($allLibIDList)
->andWhere('t1.id')->in(array_keys($docIdList))
->andWhere('t1.lib')->ne('')
->andWhere('t1.vision')->in($this->config->vision)
->beginIF($this->config->doc->notArticleType)->andWhere('t1.type')->notIN($this->config->doc->notArticleType)->fi()
->orderBy($sort)
@@ -483,7 +490,7 @@ class docModel extends model
$docs = $this->dao->select('t1.*')->from(TABLE_DOC)->alias('t1')
->leftJoin(TABLE_DOCACTION)->alias('t2')->on("t1.id=t2.doc && t2.action='collect'")
->where('t1.deleted')->eq(0)
->andWhere('t1.lib')->in($allLibIDList)
->andWhere('t1.lib')->ne('')
->andWhere('t1.id')->in($hasPrivDocIdList)
->beginIF($this->config->doc->notArticleType)->andWhere('t1.type')->notIN($this->config->doc->notArticleType)->fi()
->andWhere('t2.actor')->eq($this->app->user->account)
@@ -606,7 +613,7 @@ class docModel extends model
*/
public function getDocs($libID, $module, $browseType, $orderBy, $pager = null)
{
if(empty($libID)) return array();
if(empty($libID) and $browseType != 'all') return array();
$docIdList = $this->getPrivDocs($libID, $module, 'children');
$docs = $this->dao->select('*')->from(TABLE_DOC)
@@ -641,6 +648,9 @@ class docModel extends model
$query = preg_replace('/(`\w+`)/', 't1.$1', $query);
}
$allLibs = $this->getLibs('all');
$allLibIDList = array_keys($allLibs);
$hasPrivDocIdList = $this->getPrivDocs($allLibIDList);
if($type == 'view' or $type == 'collect')
{
$docs = $this->dao->select('t1.*,t3.name as libName,t3.type as objectType,max(t2.`date`) as date')->from(TABLE_DOC)->alias('t1')
@@ -648,6 +658,7 @@ class docModel extends model
->leftJoin(TABLE_DOCLIB)->alias('t3')->on("t1.lib=t3.id")
->where('t1.deleted')->eq(0)
->andWhere('t1.lib')->ne('')
->andWhere('t1.type')->in('text,word,ppt,excel,url,article')
->andWhere('t1.vision')->eq($this->config->vision)
->andWhere('t2.action')->eq($type)
->andWhere('t2.actor')->eq($this->app->user->account)
@@ -657,6 +668,7 @@ class docModel extends model
->beginIF($browseType == 'all' or $browseType == 'bysearch')->andWhere("(t1.status = 'normal' or (t1.status = 'draft' and t1.addedBy='{$this->app->user->account}'))")->fi()
->beginIF($browseType == 'draft')->andWhere('t1.status')->eq('draft')->andWhere('t1.addedBy')->eq($this->app->user->account)->fi()
->beginIF($browseType == 'bysearch')->andWhere($query)->fi()
->beginIF(!empty($hasPrivDocIdList))->andWhere('t1.id')->in($hasPrivDocIdList)->fi()
->groupBy('t1.id')
->orderBy($orderBy)
->page($pager, 't1.id')
@@ -680,6 +692,7 @@ class docModel extends model
->where('t1.deleted')->eq(0)
->andWhere('t1.lib')->ne('')
->andWhere('t1.vision')->eq($this->config->vision)
->andWhere('t1.type')->in('text,word,ppt,excel,url,article')
->beginIF($type == 'createdby')->andWhere('t1.addedBy')->eq($this->app->user->account)->fi()
->beginIF($type == 'editedby')->andWhere('t1.id')->in($docIdList)->fi()
->beginIF(!common::hasPriv('doc', 'productSpace'))->andWhere('t2.type')->ne('product')->fi()
@@ -899,7 +912,7 @@ class docModel extends model
unset($doc->contentMarkdown, $doc->contentType, $doc->url);
$requiredFields = $this->config->doc->create->requiredFields;
if($doc->status == 'draft') $requiredFields = '';
if($doc->status == 'draft') $requiredFields = 'title';
if(strpos("url|word|ppt|excel", $this->post->type) !== false) $requiredFields = trim(str_replace(",content,", ",", ",{$requiredFields},"), ',');
$checkContent = strpos(",$requiredFields,", ',content,') !== false;
@@ -995,7 +1008,7 @@ class docModel extends model
}
$requiredFields = $this->config->doc->edit->requiredFields;
if($doc->status == 'draft') $requiredFields = '';
if($doc->status == 'draft') $requiredFields = 'title';
if(strpos(",$requiredFields,", ',content,') !== false)
{
$requiredFields = trim(str_replace(',content,', ',', ",$requiredFields,"), ',');
@@ -1206,7 +1219,7 @@ class docModel extends model
if($libID == 0 and $browseType != 'collectedbyme') return array();
$modules = $this->dao->select('*')->from(TABLE_MODULE)
->where(1)
->where('1=1')
->beginIF($browseType != "collectedbyme")->andWhere('root')->eq($libID)->fi()
->beginIF($browseType == "collectedbyme")->andWhere('collector')->like("%,{$this->app->user->account},%")->fi()
->andWhere('type')->eq('doc')
@@ -1275,8 +1288,8 @@ class docModel extends model
{
if(empty($object)) return false;
if($this->app->user->admin and ($object->type != 'mine' or ($object->type == 'mine' and $object->addedBy == $this->app->user->account))) return true;
if($object->type == 'mine' and $object->addedBy == $this->app->user->account) return true;
if($this->app->user->admin and $object->type != 'mine') return true;
if($object->acl == 'open') return true;
$account = ',' . $this->app->user->account . ',';
@@ -1927,6 +1940,7 @@ class docModel extends model
$files = $this->dao->select('*')->from(TABLE_FILE)->alias('t1')
->where('size')->gt('0')
->andWhere('deleted')->eq('0')
->andWhere("(objectType = '$type' and objectID = $objectID)", true)
->orWhere("(objectType = 'doc' and objectID in ($docIdList))")
->orWhere("(objectType = 'bug' and objectID in ($bugIdList))")
@@ -2165,7 +2179,11 @@ class docModel extends model
{
$today = date('Y-m-d');
$statistic = new stdclass();
$statistic->totalDocs = $this->dao->select('count(*) as count')->from(TABLE_DOC)->where('deleted')->eq('0')->andWhere('vision')->eq($this->config->vision)->fetch('count');
$statistic->totalDocs = $this->dao->select('count(*) as count')->from(TABLE_DOC)
->where('deleted')->eq('0')
->andWhere('type')->in('text,word,ppt,excel,url,article')
->andWhere('vision')->eq($this->config->vision)
->fetch('count');
$statistic->todayEditedDocs = $this->dao->select('count(DISTINCT objectID) as count')->from(TABLE_ACTION)->alias('t1')
->leftJoin(TABLE_DOC)->alias('t2')->on("t1.objectID=t2.id and t1.objectType='doc'")
->where('t1.objectType')->eq('doc')
@@ -2174,17 +2192,26 @@ class docModel extends model
->andWhere('t1.vision')->eq($this->config->vision)
->andWhere('LEFT(t1.date, 10)')->eq($today)
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.type')->in('text,word,ppt,excel,url,article')
->fetch('count');
$statistic->myEditedDocs = $this->dao->select('count(DISTINCT objectID) as count')->from(TABLE_ACTION)->alias('t1')
$statistic->myEditedDocs = $this->dao->select('count(DISTINCT t1.objectID) as count')->from(TABLE_ACTION)->alias('t1')
->leftJoin(TABLE_DOC)->alias('t2')->on("t1.objectID=t2.id and t1.objectType='doc'")
->where('t1.objectType')->eq('doc')
->andWhere('t1.action')->eq('edited')
->andWhere('t1.actor')->eq($this->app->user->account)
->andWhere('t1.vision')->eq($this->config->vision)
->andWhere('t2.lib')->ne('')
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.type')->in('text,word,ppt,excel,url,article')
->fetch('count');
$my = $this->dao->select("count(*) as myDocs, SUM(views) as docViews, SUM(collects) as docCollects")->from(TABLE_DOC)->where('addedBy')->eq($this->app->user->account)->andWhere('deleted')->eq(0)->andWhere('vision')->eq($this->config->vision)->andWhere('lib')->ne(0)->fetch();
$my = $this->dao->select("count(*) as myDocs, SUM(views) as docViews, SUM(collects) as docCollects")->from(TABLE_DOC)
->where('addedBy')->eq($this->app->user->account)
->andWhere('type')->in('text,word,ppt,excel,url,article')
->andWhere('deleted')->eq(0)
->andWhere('vision')->eq($this->config->vision)
->andWhere('lib')->ne('')
->fetch();
$statistic->myDocs = $my->myDocs;
$statistic->myDoc = new stdclass();
$statistic->myDoc->docViews = $my->docViews;
@@ -2818,7 +2845,7 @@ class docModel extends model
else
{
$libs = $this->getLibsByObject($type, 0, '', $appendLib);
if($libID == 0 and !empty($libs)) $libID = reset($libs)->id;
if(($libID == 0 or !isset($libs[$libID])) and !empty($libs)) $libID = reset($libs)->id;
if(isset($libs[$libID]))
{
$objectTitle = zget($libs[$libID], 'name', '');
@@ -2830,7 +2857,9 @@ class docModel extends model
}
$tab = strpos(',doc,product,project,execution,', ",{$this->app->tab},") !== false ? $this->app->tab : 'doc';
$type = $type == 'mine' ? 'my' : $type;
if($type == 'mine') $type = 'my';
if($type == 'custom') $type = 'team';
if($tab == 'doc' and !common::hasPriv('doc', $type . 'Space')) return print(js::locate(helper::createLink('user', 'deny', "module=doc&method={$type}Space")));
if($tab != 'doc' and method_exists($type . 'Model', 'setMenu'))
{
$this->loadModel($type)->setMenu($objectID);
+3 -4
View File
@@ -5,13 +5,13 @@
<div class="cell" id="content">
<div class="detail no-padding">
<div class="detail-title no-padding doc-title">
<div class="flex-left">
<div class="title" title="<?php echo $doc->title;?>">
<?php echo $doc->title;?>
<?php if($doc->deleted):?>
<span class='label label-danger'><?php echo $lang->doc->deleted;?></span>
<?php endif;?>
</div>
<?php if($doc->status != 'draft'):?>
<div class="info">
<?php $version = $version ? $version : $doc->version;?>
@@ -25,7 +25,7 @@
<a href='javascript:;' class='btn btn-link btn-limit text-ellipsis right-dom' data-toggle='dropdown' style="max-width: 120px;">
<span class="caret"></span>
</a>
<ul id="docVersionMenu" class='dropdown-menu doc-version-menu' style='width: 250px; overflow-y:auto'>
<ul id="docVersionMenu" class='dropdown-menu doc-version-menu' style='width: 260px; overflow-y:auto'>
<li class="drop-title flex-between dropdown-header not-clear-menu"><div><?php echo $lang->doc->allVersion?></div></li>
<div class="drop-body menu-active-primary menu-hover-primary">
<?php for($itemVersion = $doc->version; $itemVersion > 0; $itemVersion--):?>
@@ -38,8 +38,7 @@
</div>
</div>
<?php endif;?>
</div>
<div class="actions">
<?php echo html::a("javascript:fullScreen()", '<span class="icon-fullscreen"></span>', '', "title='{$lang->fullscreen}' class='btn btn-link fullscreen-btn'");?>
<?php if(common::hasPriv('doc', 'collect')):?>
+1 -1
View File
@@ -30,7 +30,7 @@
<table class='table table-form'>
<?php if(strpos('product|project|execution', $type) !== false):?>
<tr>
<th><?php echo $lang->doc->project;?></th>
<th><?php echo $lang->doc->{$type};?></th>
<td class='required'><?php echo html::select($type, $objects, $objectID, "class='form-control chosen' onchange='loadObjectModules(\"{$type}\", this.value)'");?></td>
</tr>
<?php endif;?>
+6 -4
View File
@@ -76,6 +76,8 @@ li.drag-shadow ul {display: none !important;}
js::set('release', isset($release) ? $release : 0);
js::set('versionLang', $lang->build->common);
js::set('spaceType', $this->session->spaceType);
js::set('rawModule', $this->app->rawModule);
js::set('rawMethod', $this->app->rawMethod);
/* ObjectType and objectID used for other space. */
js::set('objectType', isset($type) ? $type : '');
@@ -151,7 +153,7 @@ js::set('hasLibPriv', $hasLibPriv);
<li data-method="addCataChild" data-type="add" data-id="%moduleID%" data-has-children='%hasChildren%'><a><i class="icon icon-add-directory"></i><?php echo $lang->doc->libDropdown['addSubModule'];?></a></li>
<?php endif;?>
<?php if($canEditCatalog[$module]):?>
<li data-method="editCata" class='edit-module'><a data-href='<?php echo helper::createLink($module, 'editCatalog', "moduleID=%moduleID%&type=$app->rawModule");?>'><i class="icon icon-edit"></i><?php echo $lang->doc->libDropdown['editModule'];?></a></li>
<li data-method="editCata" class='edit-module'><a data-href='<?php echo helper::createLink($module, 'editCatalog', "moduleID=%moduleID%&type=" . ($app->rawModule == 'api' ? 'api' : 'doc'));?>'><i class="icon icon-edit"></i><?php echo $lang->doc->libDropdown['editModule'];?></a></li>
<?php endif;?>
<?php if($canDeleteCatalog[$module]):?>
<li data-method="deleteCata"><a href='<?php echo helper::createLink($module, 'deleteCatalog', 'rootID=%libID%&moduleID=%moduleID%');?>' target='hiddenwin'><i class="icon icon-trash"></i><?php echo $lang->doc->libDropdown['delModule'];?></a></li>
@@ -473,8 +475,8 @@ $(function()
if(!libID) libID = 0;
if(!moduleID) moduleID = 0;
linkParams = linkParams.replace('%s', 'libID=' + libID + '&moduleID=' + moduleID);
if(config.currentModule == 'api' && config.currentMethod == 'view') spaceType = 'api';
if(spaceType != 'api' && config.currentModule == 'api') linkParams = 'objectID=' + objectID + '&' + linkParams;
if(rawModule == 'api' && rawMethod== 'view') spaceType = 'api';
if(spaceType != 'api' && rawModule == 'api') linkParams = 'objectID=' + objectID + '&' + linkParams;
var moduleName = spaceType == 'api' ? 'api' : 'doc';
var methodName = '';
if(spaceType == 'api')
@@ -624,7 +626,7 @@ $(function()
var libID = $(this).closest('#versionSwitcher').data('lib');
var moduleID = $(this).data('id');
var params = 'libID=' + libID + '&moduleID=0&apiID=0&version=0&release=' + moduleID;
var methodName = config.currentMethod;
var methodName = rawMethod;
if(config.currentModule == 'doc')
{
params = linkParams.replace('%s', 'libID=' + libID + '&moduleID=0').replace('browseType=&', 'browseType=byrelease&').replace('param=0', 'param=' + moduleID);
+1 -1
View File
@@ -126,7 +126,7 @@ body {margin-bottom: 25px;}
$spaceMethod = zget($config->doc->spaceMethod, $doc->objectType);
$spaceParams = "libID={$doc->lib}&moduleID={$doc->module}";
if(in_array($doc->objectType, array('product', 'project', 'execution', 'custom'))) $spaceParams = "objectID={$doc->objectID}&$spaceParams";
if(in_array($doc->objectType, array('mine', 'custom'))) $spaceParams = "type={$doc->objectType}&$spaceParams";
if($doc->objectType == 'mine') $spaceParams = "type={$doc->objectType}&$spaceParams";
if(common::hasPriv('doc', $spaceMethod))
{
+5 -32
View File
@@ -1873,6 +1873,8 @@ class executionModel extends model
{
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getExecutionStats($browseType);
$productID = (int)$productID;
/* Construct the query SQL at search executions. */
$executionQuery = '';
if($browseType == 'bySearch')
@@ -1915,7 +1917,7 @@ class executionModel extends model
->andWhere('t1.multiple')->eq('1')
->beginIF(!$this->app->user->admin)->andWhere('t1.id')->in($this->app->user->view->sprints)->fi()
->beginIF(!empty($executionQuery))->andWhere($executionQuery)->fi()
->beginIF($productID)->andWhere('t3.product')->eq($productID)->fi()
->beginIF($productID)->andWhere('t3.product')->eq((int)$productID)->fi()
->beginIF($projectID)->andWhere('t1.project')->eq($projectID)->fi()
->beginIF(!in_array($browseType, array('all', 'undone', 'involved', 'review', 'bySearch')))->andWhere('t1.status')->eq($browseType)->fi()
->beginIF($browseType == 'undone')->andWhere('t1.status')->notIN('done,closed')->fi()
@@ -3319,7 +3321,7 @@ class executionModel extends model
$data->branch = $storyList[$storyID]->branch;
$data->story = $storyID;
$data->version = $versions[$storyID];
$data->order = ++$lastOrder;
$data->order = (int)++$lastOrder;
$this->dao->replace(TABLE_PROJECTSTORY)->data($data)->exec();
$this->story->setStage($storyID);
@@ -4259,7 +4261,7 @@ class executionModel extends model
->page($pager, 't1.id')
->fetchAll('id');
$orderBy = str_replace('pri_', 'priOrder_', $orderBy);
$orderBy = str_replace(array('t1.pri_', 't1.`pri'), array('priOrder_', '`priOrder_'), $orderBy);
$tasks = $this->dao->select('t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.product, t2.branch, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName, IF(t1.`pri` = 0, 999, t1.`pri`) as priOrder')
->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
@@ -5784,11 +5786,6 @@ class executionModel extends model
$post = $_POST;
$_POST = array();
$extendFields = $this->getExtendFields();
foreach(array_keys($extendFields) as $field)
{
if(isset($post[$field])) $_POST[$field] = $post[$field];
}
$_POST['project'] = $projectID;
$_POST['name'] = $project->name;
@@ -5843,11 +5840,6 @@ class executionModel extends model
$post = $_POST;
$_POST = array();
$extendFields = $this->getExtendFields();
foreach(array_keys($extendFields) as $field)
{
if(isset($post[$field])) $_POST[$field] = $post[$field];
}
$_POST['project'] = $projectID;
$_POST['name'] = $project->name;
@@ -6037,23 +6029,4 @@ class executionModel extends model
}
return $sortedExecutions;
}
/**
* Get Extend Fields in workflow.
*
* @param string $module
* @access public
* @return array
*/
public function getExtendFields($module = 'project')
{
$extendFields = $this->dao->select('field')
->from(TABLE_WORKFLOWFIELD)
->where('module')->eq('project')
->andWhere('buildin')->eq(0)
->andWhere('role')->eq('custom')
->fetchPairs('field');
return $extendFields;
}
}
+13 -4
View File
@@ -197,7 +197,7 @@ class group extends control
* @access public
* @return void
*/
public function managePriv($type = 'byGroup', $param = 0, $menu = '', $version = '')
public function managePriv($type = 'byPackage', $param = 0, $menu = '', $version = '')
{
if($type == 'byGroup' or $type == 'byPackage') $groupID = $param;
@@ -251,13 +251,19 @@ class group extends control
$privs = $this->group->transformPrivLang($privs);
$privs = $this->group->getCustomPrivs($menu, $privs);
$privList = $modules;
$privMethods = array();
$selectPrivs = array();
$selectedPrivIdList = array();
$groupPrivsIdList = $this->group->getPrivsIdListByGroup($groupID);
foreach($privs as $priv)
{
if(!empty($version) and strpos($changelogs, ",{$priv->module}-{$priv->method},") === false) continue;
if(!empty($version) and strpos($changelogs, ",{$priv->module}-{$priv->method},") === false)
{
unset($groupPrivsIdList[$priv->id]);
continue;
}
if(!isset($privList[$priv->parentCode])) $privList[$priv->parentCode] = array();
if(!is_array($privList[$priv->parentCode])) $privList[$priv->parentCode] = array();
@@ -305,7 +311,6 @@ class group extends control
}
}
$groupPrivsIdList = $this->group->getPrivsIdListByGroup($groupID);
$excludePrivsIdList = array_diff(array_keys($groupPrivsIdList), $selectedPrivIdList);
$relatedPrivData = $this->group->getRelatedPrivs($selectedPrivIdList, '', $excludePrivsIdList);
@@ -329,7 +334,11 @@ class group extends control
$privs = $this->group->getCustomPrivs('', $privs);
$modules = $this->dao->select('*')->from(TABLE_PRIVMANAGER)->where('type')->eq('module')->fetchAll('code');
$modulePairs = $this->group->getPrivManagerPairs('module');
$unassignedModules = array_diff(array_keys(array_filter(get_object_vars($this->lang->resource), function($modulePrivs){return !empty((array)$modulePrivs);})), array_keys($modulePairs));
$privArray = get_object_vars($this->lang->resource);
$privArray = array_filter($privArray, function($modulePrivs){$modulePrivs = (array)$modulePrivs; return !empty($modulePrivs);});
$unassignedModules = array_diff(array_keys($privArray), array_keys($modulePairs));
foreach($unassignedModules as $unassignedModule)
{
$this->app->loadLang($unassignedModule);
+24 -24
View File
@@ -664,27 +664,27 @@ $lang->changelog['18.3'][] = 'editor-newPage';
$lang->changelog['18.3'][] = 'editor-save';
$lang->changelog['18.3'][] = 'editor-delete';
$lang->changelog['18.4'][] = 'doc-mySpace';
$lang->changelog['18.4'][] = 'doc-myView';
$lang->changelog['18.4'][] = 'doc-myCollection';
$lang->changelog['18.4'][] = 'doc-myCreation';
$lang->changelog['18.4'][] = 'doc-productSpace';
$lang->changelog['18.4'][] = 'doc-projectSpace';
$lang->changelog['18.4'][] = 'doc-teamSpace';
$lang->changelog['18.4'][] = 'doc-addCatalog';
$lang->changelog['18.4'][] = 'doc-editCatalog';
$lang->changelog['18.4'][] = 'doc-deleteCatalog';
$lang->changelog['18.4'][] = 'doc-displaySetting';
$lang->changelog['18.4'][] = 'group-batchChangePackage';
$lang->changelog['18.4'][] = 'screen-annualData';
$lang->changelog['18.4'][] = 'screen-allAnnualData';
$lang->changelog['18.4'][] = 'pivot-preview';
$lang->changelog['18.4'][] = 'pivot-productSummary';
$lang->changelog['18.4'][] = 'pivot-projectDeviation';
$lang->changelog['18.4'][] = 'pivot-bugCreate';
$lang->changelog['18.4'][] = 'pivot-bugAssign';
$lang->changelog['18.4'][] = 'pivot-workload';
$lang->changelog['18.4'][] = 'chart-preview';
$lang->changelog['18.4'][] = 'api-addCatalog';
$lang->changelog['18.4'][] = 'api-editCatalog';
$lang->changelog['18.4'][] = 'api-deleteCatalog';
$lang->changelog['18.4.alpha1'][] = 'doc-mySpace';
$lang->changelog['18.4.alpha1'][] = 'doc-myView';
$lang->changelog['18.4.alpha1'][] = 'doc-myCollection';
$lang->changelog['18.4.alpha1'][] = 'doc-myCreation';
$lang->changelog['18.4.alpha1'][] = 'doc-productSpace';
$lang->changelog['18.4.alpha1'][] = 'doc-projectSpace';
$lang->changelog['18.4.alpha1'][] = 'doc-teamSpace';
$lang->changelog['18.4.alpha1'][] = 'doc-addCatalog';
$lang->changelog['18.4.alpha1'][] = 'doc-editCatalog';
$lang->changelog['18.4.alpha1'][] = 'doc-deleteCatalog';
$lang->changelog['18.4.alpha1'][] = 'doc-displaySetting';
$lang->changelog['18.4.alpha1'][] = 'group-batchChangePackage';
$lang->changelog['18.4.alpha1'][] = 'screen-annualData';
$lang->changelog['18.4.alpha1'][] = 'screen-allAnnualData';
$lang->changelog['18.4.alpha1'][] = 'pivot-preview';
$lang->changelog['18.4.alpha1'][] = 'pivot-productSummary';
$lang->changelog['18.4.alpha1'][] = 'pivot-projectDeviation';
$lang->changelog['18.4.alpha1'][] = 'pivot-bugCreate';
$lang->changelog['18.4.alpha1'][] = 'pivot-bugAssign';
$lang->changelog['18.4.alpha1'][] = 'pivot-workload';
$lang->changelog['18.4.alpha1'][] = 'chart-preview';
$lang->changelog['18.4.alpha1'][] = 'api-addCatalog';
$lang->changelog['18.4.alpha1'][] = 'api-editCatalog';
$lang->changelog['18.4.alpha1'][] = 'api-deleteCatalog';
+81 -81
View File
@@ -121,86 +121,86 @@ $lang->privpackage->belong = 'Priv Package';
$lang->group->copyOptions['copyPriv'] = 'Rechte kopieren';
$lang->group->copyOptions['copyUser'] = 'Benutzer kopieren';
$lang->group->versions[''] = 'Verlauf';
$lang->group->versions['18_4'] = 'ZenTao18.4';
$lang->group->versions['18_3'] = 'ZenTao18.3';
$lang->group->versions['18_2'] = 'ZenTao18.2';
$lang->group->versions['18_1'] = 'ZenTao18.1';
$lang->group->versions['18_0'] = 'ZenTao18.0';
$lang->group->versions['18_0_beta3'] = 'ZenTao18.0.beta3';
$lang->group->versions['18_0_beta2'] = 'ZenTao18.0.beta2';
$lang->group->versions['18_0_beta1'] = 'ZenTao18.0.beta1';
$lang->group->versions['17_6_2'] = 'ZenTao17.6.2';
$lang->group->versions['17_6'] = 'ZenTao17.6';
$lang->group->versions['17_5'] = 'ZenTao17.5';
$lang->group->versions['17_4'] = 'ZenTao17.4';
$lang->group->versions['17_3'] = 'ZenTao17.3';
$lang->group->versions['17_2'] = 'ZenTao17.2';
$lang->group->versions['17_1'] = 'ZenTao17.1';
$lang->group->versions['17_0_beta2'] = 'ZenTao17.0.beta2';
$lang->group->versions['17_0_beta1'] = 'ZenTao17.0.beta1';
$lang->group->versions['16_5_beta1'] = 'ZenTao16.5.beta1';
$lang->group->versions['16_4'] = 'ZenTao16.4';
$lang->group->versions['16_3'] = 'ZenTao16.3';
$lang->group->versions['16_2'] = 'ZenTao16.2';
$lang->group->versions['16_1'] = 'ZenTao16.1';
$lang->group->versions['16_0'] = 'ZenTao16.0';
$lang->group->versions['16_0_beta1'] = 'ZenTao16.0.beta1';
$lang->group->versions['15_8'] = 'ZenTao15.8';
$lang->group->versions['15_7'] = 'ZenTao15.7';
$lang->group->versions['15_0_rc1'] = 'ZenTao15.0.rc1';
$lang->group->versions['12_5'] = 'ZenTao12.5';
$lang->group->versions['12_3'] = 'ZenTao12.3';
$lang->group->versions['11_6_2'] = 'ZenTao11.6.2';
$lang->group->versions['10_6'] = 'ZenTao10.6';
$lang->group->versions['10_1'] = 'ZenTao10.1';
$lang->group->versions['10_0_alpha'] = 'ZenTao10.0.alpha';
$lang->group->versions['9_8'] = 'ZenTao9.8';
$lang->group->versions['9_6'] = 'ZenTao9.6';
$lang->group->versions['9_5'] = 'ZenTao9.5';
$lang->group->versions['9_2'] = 'ZenTao9.2';
$lang->group->versions['9_1'] = 'ZenTao9.1';
$lang->group->versions['9_0'] = 'ZenTao9.0';
$lang->group->versions['8_4'] = 'ZenTao8.4';
$lang->group->versions['8_3'] = 'ZenTao8.3';
$lang->group->versions['8_2_beta'] = 'ZenTao8.2.beta';
$lang->group->versions['8_0_1'] = 'ZenTao8.0.1';
$lang->group->versions['8_0'] = 'ZenTao8.0';
$lang->group->versions['7_4_beta'] = 'ZenTao7.4.beta';
$lang->group->versions['7_3'] = 'ZenTao7.3';
$lang->group->versions['7_2'] = 'ZenTao7.2';
$lang->group->versions['7_1'] = 'ZenTao7.1';
$lang->group->versions['6_4'] = 'ZenTao6.4';
$lang->group->versions['6_3'] = 'ZenTao6.3';
$lang->group->versions['6_2'] = 'ZenTao6.2';
$lang->group->versions['6_1'] = 'ZenTao6.1';
$lang->group->versions['5_3'] = 'ZenTao5.3';
$lang->group->versions['5_1'] = 'ZenTao5.1';
$lang->group->versions['5_0_beta2'] = 'ZenTao5.0.beta2';
$lang->group->versions['5_0_beta1'] = 'ZenTao5.0.beta1';
$lang->group->versions['4_3_beta'] = 'ZenTao4.3.beta';
$lang->group->versions['4_2_beta'] = 'ZenTao4.2.beta';
$lang->group->versions['4_1'] = 'ZenTao4.1';
$lang->group->versions['4_0_1'] = 'ZenTao4.0.1';
$lang->group->versions['4_0'] = 'ZenTao4.0';
$lang->group->versions['4_0_beta2'] = 'ZenTao4.0.beta2';
$lang->group->versions['4_0_beta1'] = 'ZenTao4.0.beta1';
$lang->group->versions['3_3'] = 'ZenTao3.3';
$lang->group->versions['3_2_1'] = 'ZenTao3.2.1';
$lang->group->versions['3_2'] = 'ZenTao3.2';
$lang->group->versions['3_1'] = 'ZenTao3.1';
$lang->group->versions['3_0_beta2'] = 'ZenTao3.0.beta2';
$lang->group->versions['3_0_beta1'] = 'ZenTao3.0.beta1';
$lang->group->versions['2_4'] = 'ZenTao2.4';
$lang->group->versions['2_3'] = 'ZenTao2.3';
$lang->group->versions['2_2'] = 'ZenTao2.2';
$lang->group->versions['2_1'] = 'ZenTao2.1';
$lang->group->versions['2_0'] = 'ZenTao2.0';
$lang->group->versions['1_5'] = 'ZenTao1.5';
$lang->group->versions['1_4'] = 'ZenTao1.4';
$lang->group->versions['1_3'] = 'ZenTao1.3';
$lang->group->versions['1_2'] = 'ZenTao1.2';
$lang->group->versions['1_1'] = 'ZenTao1.1';
$lang->group->versions['1_0_1'] = 'ZenTao1.0.1';
$lang->group->versions[''] = 'Verlauf';
$lang->group->versions['18_4_alpha1'] = 'ZenTao18.4.alpha1';
$lang->group->versions['18_3'] = 'ZenTao18.3';
$lang->group->versions['18_2'] = 'ZenTao18.2';
$lang->group->versions['18_1'] = 'ZenTao18.1';
$lang->group->versions['18_0'] = 'ZenTao18.0';
$lang->group->versions['18_0_beta3'] = 'ZenTao18.0.beta3';
$lang->group->versions['18_0_beta2'] = 'ZenTao18.0.beta2';
$lang->group->versions['18_0_beta1'] = 'ZenTao18.0.beta1';
$lang->group->versions['17_6_2'] = 'ZenTao17.6.2';
$lang->group->versions['17_6'] = 'ZenTao17.6';
$lang->group->versions['17_5'] = 'ZenTao17.5';
$lang->group->versions['17_4'] = 'ZenTao17.4';
$lang->group->versions['17_3'] = 'ZenTao17.3';
$lang->group->versions['17_2'] = 'ZenTao17.2';
$lang->group->versions['17_1'] = 'ZenTao17.1';
$lang->group->versions['17_0_beta2'] = 'ZenTao17.0.beta2';
$lang->group->versions['17_0_beta1'] = 'ZenTao17.0.beta1';
$lang->group->versions['16_5_beta1'] = 'ZenTao16.5.beta1';
$lang->group->versions['16_4'] = 'ZenTao16.4';
$lang->group->versions['16_3'] = 'ZenTao16.3';
$lang->group->versions['16_2'] = 'ZenTao16.2';
$lang->group->versions['16_1'] = 'ZenTao16.1';
$lang->group->versions['16_0'] = 'ZenTao16.0';
$lang->group->versions['16_0_beta1'] = 'ZenTao16.0.beta1';
$lang->group->versions['15_8'] = 'ZenTao15.8';
$lang->group->versions['15_7'] = 'ZenTao15.7';
$lang->group->versions['15_0_rc1'] = 'ZenTao15.0.rc1';
$lang->group->versions['12_5'] = 'ZenTao12.5';
$lang->group->versions['12_3'] = 'ZenTao12.3';
$lang->group->versions['11_6_2'] = 'ZenTao11.6.2';
$lang->group->versions['10_6'] = 'ZenTao10.6';
$lang->group->versions['10_1'] = 'ZenTao10.1';
$lang->group->versions['10_0_alpha'] = 'ZenTao10.0.alpha';
$lang->group->versions['9_8'] = 'ZenTao9.8';
$lang->group->versions['9_6'] = 'ZenTao9.6';
$lang->group->versions['9_5'] = 'ZenTao9.5';
$lang->group->versions['9_2'] = 'ZenTao9.2';
$lang->group->versions['9_1'] = 'ZenTao9.1';
$lang->group->versions['9_0'] = 'ZenTao9.0';
$lang->group->versions['8_4'] = 'ZenTao8.4';
$lang->group->versions['8_3'] = 'ZenTao8.3';
$lang->group->versions['8_2_beta'] = 'ZenTao8.2.beta';
$lang->group->versions['8_0_1'] = 'ZenTao8.0.1';
$lang->group->versions['8_0'] = 'ZenTao8.0';
$lang->group->versions['7_4_beta'] = 'ZenTao7.4.beta';
$lang->group->versions['7_3'] = 'ZenTao7.3';
$lang->group->versions['7_2'] = 'ZenTao7.2';
$lang->group->versions['7_1'] = 'ZenTao7.1';
$lang->group->versions['6_4'] = 'ZenTao6.4';
$lang->group->versions['6_3'] = 'ZenTao6.3';
$lang->group->versions['6_2'] = 'ZenTao6.2';
$lang->group->versions['6_1'] = 'ZenTao6.1';
$lang->group->versions['5_3'] = 'ZenTao5.3';
$lang->group->versions['5_1'] = 'ZenTao5.1';
$lang->group->versions['5_0_beta2'] = 'ZenTao5.0.beta2';
$lang->group->versions['5_0_beta1'] = 'ZenTao5.0.beta1';
$lang->group->versions['4_3_beta'] = 'ZenTao4.3.beta';
$lang->group->versions['4_2_beta'] = 'ZenTao4.2.beta';
$lang->group->versions['4_1'] = 'ZenTao4.1';
$lang->group->versions['4_0_1'] = 'ZenTao4.0.1';
$lang->group->versions['4_0'] = 'ZenTao4.0';
$lang->group->versions['4_0_beta2'] = 'ZenTao4.0.beta2';
$lang->group->versions['4_0_beta1'] = 'ZenTao4.0.beta1';
$lang->group->versions['3_3'] = 'ZenTao3.3';
$lang->group->versions['3_2_1'] = 'ZenTao3.2.1';
$lang->group->versions['3_2'] = 'ZenTao3.2';
$lang->group->versions['3_1'] = 'ZenTao3.1';
$lang->group->versions['3_0_beta2'] = 'ZenTao3.0.beta2';
$lang->group->versions['3_0_beta1'] = 'ZenTao3.0.beta1';
$lang->group->versions['2_4'] = 'ZenTao2.4';
$lang->group->versions['2_3'] = 'ZenTao2.3';
$lang->group->versions['2_2'] = 'ZenTao2.2';
$lang->group->versions['2_1'] = 'ZenTao2.1';
$lang->group->versions['2_0'] = 'ZenTao2.0';
$lang->group->versions['1_5'] = 'ZenTao1.5';
$lang->group->versions['1_4'] = 'ZenTao1.4';
$lang->group->versions['1_3'] = 'ZenTao1.3';
$lang->group->versions['1_2'] = 'ZenTao1.2';
$lang->group->versions['1_1'] = 'ZenTao1.1';
$lang->group->versions['1_0_1'] = 'ZenTao1.0.1';
include (dirname(__FILE__) . '/resource.php');
+81 -81
View File
@@ -121,86 +121,86 @@ $lang->privpackage->belong = 'Priv Package';
$lang->group->copyOptions['copyPriv'] = 'Copy Privileges';
$lang->group->copyOptions['copyUser'] = 'Copy Users';
$lang->group->versions[''] = 'History';
$lang->group->versions['18_4'] = 'ZenTao18.4';
$lang->group->versions['18_3'] = 'ZenTao18.3';
$lang->group->versions['18_2'] = 'ZenTao18.2';
$lang->group->versions['18_1'] = 'ZenTao18.1';
$lang->group->versions['18_0'] = 'ZenTao18.0';
$lang->group->versions['18_0_beta3'] = 'ZenTao18.0.beta3';
$lang->group->versions['18_0_beta2'] = 'ZenTao18.0.beta2';
$lang->group->versions['18_0_beta1'] = 'ZenTao18.0.beta1';
$lang->group->versions['17_6_2'] = 'ZenTao17.6.2';
$lang->group->versions['17_6'] = 'ZenTao17.6';
$lang->group->versions['17_5'] = 'ZenTao17.5';
$lang->group->versions['17_4'] = 'ZenTao17.4';
$lang->group->versions['17_3'] = 'ZenTao17.3';
$lang->group->versions['17_2'] = 'ZenTao17.2';
$lang->group->versions['17_1'] = 'ZenTao17.1';
$lang->group->versions['17_0_beta2'] = 'ZenTao17.0.beta2';
$lang->group->versions['17_0_beta1'] = 'ZenTao17.0.beta1';
$lang->group->versions['16_5_beta1'] = 'ZenTao16.5.beta1';
$lang->group->versions['16_4'] = 'ZenTao16.4';
$lang->group->versions['16_3'] = 'ZenTao16.3';
$lang->group->versions['16_2'] = 'ZenTao16.2';
$lang->group->versions['16_1'] = 'ZenTao16.1';
$lang->group->versions['16_0'] = 'ZenTao16.0';
$lang->group->versions['16_0_beta1'] = 'ZenTao16.0.beta1';
$lang->group->versions['15_8'] = 'ZenTao15.8';
$lang->group->versions['15_7'] = 'ZenTao15.7';
$lang->group->versions['15_0_rc1'] = 'ZenTao15.0.rc1';
$lang->group->versions['12_5'] = 'ZenTao12.5';
$lang->group->versions['12_3'] = 'ZenTao12.3';
$lang->group->versions['11_6_2'] = 'ZenTao11.6.2';
$lang->group->versions['10_6'] = 'ZenTao10.6';
$lang->group->versions['10_1'] = 'ZenTao10.1';
$lang->group->versions['10_0_alpha'] = 'ZenTao10.0.alpha';
$lang->group->versions['9_8'] = 'ZenTao9.8';
$lang->group->versions['9_6'] = 'ZenTao9.6';
$lang->group->versions['9_5'] = 'ZenTao9.5';
$lang->group->versions['9_2'] = 'ZenTao9.2';
$lang->group->versions['9_1'] = 'ZenTao9.1';
$lang->group->versions['9_0'] = 'ZenTao9.0';
$lang->group->versions['8_4'] = 'ZenTao8.4';
$lang->group->versions['8_3'] = 'ZenTao8.3';
$lang->group->versions['8_2_beta'] = 'ZenTao8.2.beta';
$lang->group->versions['8_0_1'] = 'ZenTao8.0.1';
$lang->group->versions['8_0'] = 'ZenTao8.0';
$lang->group->versions['7_4_beta'] = 'ZenTao7.4.beta';
$lang->group->versions['7_3'] = 'ZenTao7.3';
$lang->group->versions['7_2'] = 'ZenTao7.2';
$lang->group->versions['7_1'] = 'ZenTao7.1';
$lang->group->versions['6_4'] = 'ZenTao6.4';
$lang->group->versions['6_3'] = 'ZenTao6.3';
$lang->group->versions['6_2'] = 'ZenTao6.2';
$lang->group->versions['6_1'] = 'ZenTao6.1';
$lang->group->versions['5_3'] = 'ZenTao5.3';
$lang->group->versions['5_1'] = 'ZenTao5.1';
$lang->group->versions['5_0_beta2'] = 'ZenTao5.0.beta2';
$lang->group->versions['5_0_beta1'] = 'ZenTao5.0.beta1';
$lang->group->versions['4_3_beta'] = 'ZenTao4.3.beta';
$lang->group->versions['4_2_beta'] = 'ZenTao4.2.beta';
$lang->group->versions['4_1'] = 'ZenTao4.1';
$lang->group->versions['4_0_1'] = 'ZenTao4.0.1';
$lang->group->versions['4_0'] = 'ZenTao4.0';
$lang->group->versions['4_0_beta2'] = 'ZenTao4.0.beta2';
$lang->group->versions['4_0_beta1'] = 'ZenTao4.0.beta1';
$lang->group->versions['3_3'] = 'ZenTao3.3';
$lang->group->versions['3_2_1'] = 'ZenTao3.2.1';
$lang->group->versions['3_2'] = 'ZenTao3.2';
$lang->group->versions['3_1'] = 'ZenTao3.1';
$lang->group->versions['3_0_beta2'] = 'ZenTao3.0.beta2';
$lang->group->versions['3_0_beta1'] = 'ZenTao3.0.beta1';
$lang->group->versions['2_4'] = 'ZenTao2.4';
$lang->group->versions['2_3'] = 'ZenTao2.3';
$lang->group->versions['2_2'] = 'ZenTao2.2';
$lang->group->versions['2_1'] = 'ZenTao2.1';
$lang->group->versions['2_0'] = 'ZenTao2.0';
$lang->group->versions['1_5'] = 'ZenTao1.5';
$lang->group->versions['1_4'] = 'ZenTao1.4';
$lang->group->versions['1_3'] = 'ZenTao1.3';
$lang->group->versions['1_2'] = 'ZenTao1.2';
$lang->group->versions['1_1'] = 'ZenTao1.1';
$lang->group->versions['1_0_1'] = 'ZenTao1.0.1';
$lang->group->versions[''] = 'History';
$lang->group->versions['18_4_alpha1'] = 'ZenTao18.4.alpha1';
$lang->group->versions['18_3'] = 'ZenTao18.3';
$lang->group->versions['18_2'] = 'ZenTao18.2';
$lang->group->versions['18_1'] = 'ZenTao18.1';
$lang->group->versions['18_0'] = 'ZenTao18.0';
$lang->group->versions['18_0_beta3'] = 'ZenTao18.0.beta3';
$lang->group->versions['18_0_beta2'] = 'ZenTao18.0.beta2';
$lang->group->versions['18_0_beta1'] = 'ZenTao18.0.beta1';
$lang->group->versions['17_6_2'] = 'ZenTao17.6.2';
$lang->group->versions['17_6'] = 'ZenTao17.6';
$lang->group->versions['17_5'] = 'ZenTao17.5';
$lang->group->versions['17_4'] = 'ZenTao17.4';
$lang->group->versions['17_3'] = 'ZenTao17.3';
$lang->group->versions['17_2'] = 'ZenTao17.2';
$lang->group->versions['17_1'] = 'ZenTao17.1';
$lang->group->versions['17_0_beta2'] = 'ZenTao17.0.beta2';
$lang->group->versions['17_0_beta1'] = 'ZenTao17.0.beta1';
$lang->group->versions['16_5_beta1'] = 'ZenTao16.5.beta1';
$lang->group->versions['16_4'] = 'ZenTao16.4';
$lang->group->versions['16_3'] = 'ZenTao16.3';
$lang->group->versions['16_2'] = 'ZenTao16.2';
$lang->group->versions['16_1'] = 'ZenTao16.1';
$lang->group->versions['16_0'] = 'ZenTao16.0';
$lang->group->versions['16_0_beta1'] = 'ZenTao16.0.beta1';
$lang->group->versions['15_8'] = 'ZenTao15.8';
$lang->group->versions['15_7'] = 'ZenTao15.7';
$lang->group->versions['15_0_rc1'] = 'ZenTao15.0.rc1';
$lang->group->versions['12_5'] = 'ZenTao12.5';
$lang->group->versions['12_3'] = 'ZenTao12.3';
$lang->group->versions['11_6_2'] = 'ZenTao11.6.2';
$lang->group->versions['10_6'] = 'ZenTao10.6';
$lang->group->versions['10_1'] = 'ZenTao10.1';
$lang->group->versions['10_0_alpha'] = 'ZenTao10.0.alpha';
$lang->group->versions['9_8'] = 'ZenTao9.8';
$lang->group->versions['9_6'] = 'ZenTao9.6';
$lang->group->versions['9_5'] = 'ZenTao9.5';
$lang->group->versions['9_2'] = 'ZenTao9.2';
$lang->group->versions['9_1'] = 'ZenTao9.1';
$lang->group->versions['9_0'] = 'ZenTao9.0';
$lang->group->versions['8_4'] = 'ZenTao8.4';
$lang->group->versions['8_3'] = 'ZenTao8.3';
$lang->group->versions['8_2_beta'] = 'ZenTao8.2.beta';
$lang->group->versions['8_0_1'] = 'ZenTao8.0.1';
$lang->group->versions['8_0'] = 'ZenTao8.0';
$lang->group->versions['7_4_beta'] = 'ZenTao7.4.beta';
$lang->group->versions['7_3'] = 'ZenTao7.3';
$lang->group->versions['7_2'] = 'ZenTao7.2';
$lang->group->versions['7_1'] = 'ZenTao7.1';
$lang->group->versions['6_4'] = 'ZenTao6.4';
$lang->group->versions['6_3'] = 'ZenTao6.3';
$lang->group->versions['6_2'] = 'ZenTao6.2';
$lang->group->versions['6_1'] = 'ZenTao6.1';
$lang->group->versions['5_3'] = 'ZenTao5.3';
$lang->group->versions['5_1'] = 'ZenTao5.1';
$lang->group->versions['5_0_beta2'] = 'ZenTao5.0.beta2';
$lang->group->versions['5_0_beta1'] = 'ZenTao5.0.beta1';
$lang->group->versions['4_3_beta'] = 'ZenTao4.3.beta';
$lang->group->versions['4_2_beta'] = 'ZenTao4.2.beta';
$lang->group->versions['4_1'] = 'ZenTao4.1';
$lang->group->versions['4_0_1'] = 'ZenTao4.0.1';
$lang->group->versions['4_0'] = 'ZenTao4.0';
$lang->group->versions['4_0_beta2'] = 'ZenTao4.0.beta2';
$lang->group->versions['4_0_beta1'] = 'ZenTao4.0.beta1';
$lang->group->versions['3_3'] = 'ZenTao3.3';
$lang->group->versions['3_2_1'] = 'ZenTao3.2.1';
$lang->group->versions['3_2'] = 'ZenTao3.2';
$lang->group->versions['3_1'] = 'ZenTao3.1';
$lang->group->versions['3_0_beta2'] = 'ZenTao3.0.beta2';
$lang->group->versions['3_0_beta1'] = 'ZenTao3.0.beta1';
$lang->group->versions['2_4'] = 'ZenTao2.4';
$lang->group->versions['2_3'] = 'ZenTao2.3';
$lang->group->versions['2_2'] = 'ZenTao2.2';
$lang->group->versions['2_1'] = 'ZenTao2.1';
$lang->group->versions['2_0'] = 'ZenTao2.0';
$lang->group->versions['1_5'] = 'ZenTao1.5';
$lang->group->versions['1_4'] = 'ZenTao1.4';
$lang->group->versions['1_3'] = 'ZenTao1.3';
$lang->group->versions['1_2'] = 'ZenTao1.2';
$lang->group->versions['1_1'] = 'ZenTao1.1';
$lang->group->versions['1_0_1'] = 'ZenTao1.0.1';
include (dirname(__FILE__) . '/resource.php');
+81 -81
View File
@@ -121,86 +121,86 @@ $lang->privpackage->belong = 'Priv Package';
$lang->group->copyOptions['copyPriv'] = 'Copier Privilèges';
$lang->group->copyOptions['copyUser'] = 'Copier Utilisateurs';
$lang->group->versions[''] = 'History';
$lang->group->versions['18_4'] = 'ZenTao18.4';
$lang->group->versions['18_3'] = 'ZenTao18.3';
$lang->group->versions['18_2'] = 'ZenTao18.2';
$lang->group->versions['18_1'] = 'ZenTao18.1';
$lang->group->versions['18_0'] = 'ZenTao18.0';
$lang->group->versions['18_0_beta3'] = 'ZenTao18.0.beta3';
$lang->group->versions['18_0_beta2'] = 'ZenTao18.0.beta2';
$lang->group->versions['18_0_beta1'] = 'ZenTao18.0.beta1';
$lang->group->versions['17_6_2'] = 'ZenTao17.6.2';
$lang->group->versions['17_6'] = 'ZenTao17.6';
$lang->group->versions['17_5'] = 'ZenTao17.5';
$lang->group->versions['17_4'] = 'ZenTao17.4';
$lang->group->versions['17_3'] = 'ZenTao17.3';
$lang->group->versions['17_2'] = 'ZenTao17.2';
$lang->group->versions['17_1'] = 'ZenTao17.1';
$lang->group->versions['17_0_beta2'] = 'ZenTao17.0.beta2';
$lang->group->versions['17_0_beta1'] = 'ZenTao17.0.beta1';
$lang->group->versions['16_5_beta1'] = 'ZenTao16.5.beta1';
$lang->group->versions['16_4'] = 'ZenTao16.4';
$lang->group->versions['16_3'] = 'ZenTao16.3';
$lang->group->versions['16_2'] = 'ZenTao16.2';
$lang->group->versions['16_1'] = 'ZenTao16.1';
$lang->group->versions['16_0'] = 'ZenTao16.0';
$lang->group->versions['16_0_beta1'] = 'ZenTao16.0.beta1';
$lang->group->versions['15_8'] = 'ZenTao15.8';
$lang->group->versions['15_7'] = 'ZenTao15.7';
$lang->group->versions['15_0_rc1'] = 'ZenTao15.0.rc1';
$lang->group->versions['12_5'] = 'ZenTao12.5';
$lang->group->versions['12_3'] = 'ZenTao12.3';
$lang->group->versions['11_6_2'] = 'ZenTao11.6.2';
$lang->group->versions['10_6'] = 'ZenTao10.6';
$lang->group->versions['10_1'] = 'ZenTao10.1';
$lang->group->versions['10_0_alpha'] = 'ZenTao10.0.alpha';
$lang->group->versions['9_8'] = 'ZenTao9.8';
$lang->group->versions['9_6'] = 'ZenTao9.6';
$lang->group->versions['9_5'] = 'ZenTao9.5';
$lang->group->versions['9_2'] = 'ZenTao9.2';
$lang->group->versions['9_1'] = 'ZenTao9.1';
$lang->group->versions['9_0'] = 'ZenTao9.0';
$lang->group->versions['8_4'] = 'ZenTao8.4';
$lang->group->versions['8_3'] = 'ZenTao8.3';
$lang->group->versions['8_2_beta'] = 'ZenTao8.2.beta';
$lang->group->versions['8_0_1'] = 'ZenTao8.0.1';
$lang->group->versions['8_0'] = 'ZenTao8.0';
$lang->group->versions['7_4_beta'] = 'ZenTao7.4.beta';
$lang->group->versions['7_3'] = 'ZenTao7.3';
$lang->group->versions['7_2'] = 'ZenTao7.2';
$lang->group->versions['7_1'] = 'ZenTao7.1';
$lang->group->versions['6_4'] = 'ZenTao6.4';
$lang->group->versions['6_3'] = 'ZenTao6.3';
$lang->group->versions['6_2'] = 'ZenTao6.2';
$lang->group->versions['6_1'] = 'ZenTao6.1';
$lang->group->versions['5_3'] = 'ZenTao5.3';
$lang->group->versions['5_1'] = 'ZenTao5.1';
$lang->group->versions['5_0_beta2'] = 'ZenTao5.0.beta2';
$lang->group->versions['5_0_beta1'] = 'ZenTao5.0.beta1';
$lang->group->versions['4_3_beta'] = 'ZenTao4.3.beta';
$lang->group->versions['4_2_beta'] = 'ZenTao4.2.beta';
$lang->group->versions['4_1'] = 'ZenTao4.1';
$lang->group->versions['4_0_1'] = 'ZenTao4.0.1';
$lang->group->versions['4_0'] = 'ZenTao4.0';
$lang->group->versions['4_0_beta2'] = 'ZenTao4.0.beta2';
$lang->group->versions['4_0_beta1'] = 'ZenTao4.0.beta1';
$lang->group->versions['3_3'] = 'ZenTao3.3';
$lang->group->versions['3_2_1'] = 'ZenTao3.2.1';
$lang->group->versions['3_2'] = 'ZenTao3.2';
$lang->group->versions['3_1'] = 'ZenTao3.1';
$lang->group->versions['3_0_beta2'] = 'ZenTao3.0.beta2';
$lang->group->versions['3_0_beta1'] = 'ZenTao3.0.beta1';
$lang->group->versions['2_4'] = 'ZenTao2.4';
$lang->group->versions['2_3'] = 'ZenTao2.3';
$lang->group->versions['2_2'] = 'ZenTao2.2';
$lang->group->versions['2_1'] = 'ZenTao2.1';
$lang->group->versions['2_0'] = 'ZenTao2.0';
$lang->group->versions['1_5'] = 'ZenTao1.5';
$lang->group->versions['1_4'] = 'ZenTao1.4';
$lang->group->versions['1_3'] = 'ZenTao1.3';
$lang->group->versions['1_2'] = 'ZenTao1.2';
$lang->group->versions['1_1'] = 'ZenTao1.1';
$lang->group->versions['1_0_1'] = 'ZenTao1.0.1';
$lang->group->versions[''] = 'History';
$lang->group->versions['18_4_alpha1'] = 'ZenTao18.4.alpha1';
$lang->group->versions['18_3'] = 'ZenTao18.3';
$lang->group->versions['18_2'] = 'ZenTao18.2';
$lang->group->versions['18_1'] = 'ZenTao18.1';
$lang->group->versions['18_0'] = 'ZenTao18.0';
$lang->group->versions['18_0_beta3'] = 'ZenTao18.0.beta3';
$lang->group->versions['18_0_beta2'] = 'ZenTao18.0.beta2';
$lang->group->versions['18_0_beta1'] = 'ZenTao18.0.beta1';
$lang->group->versions['17_6_2'] = 'ZenTao17.6.2';
$lang->group->versions['17_6'] = 'ZenTao17.6';
$lang->group->versions['17_5'] = 'ZenTao17.5';
$lang->group->versions['17_4'] = 'ZenTao17.4';
$lang->group->versions['17_3'] = 'ZenTao17.3';
$lang->group->versions['17_2'] = 'ZenTao17.2';
$lang->group->versions['17_1'] = 'ZenTao17.1';
$lang->group->versions['17_0_beta2'] = 'ZenTao17.0.beta2';
$lang->group->versions['17_0_beta1'] = 'ZenTao17.0.beta1';
$lang->group->versions['16_5_beta1'] = 'ZenTao16.5.beta1';
$lang->group->versions['16_4'] = 'ZenTao16.4';
$lang->group->versions['16_3'] = 'ZenTao16.3';
$lang->group->versions['16_2'] = 'ZenTao16.2';
$lang->group->versions['16_1'] = 'ZenTao16.1';
$lang->group->versions['16_0'] = 'ZenTao16.0';
$lang->group->versions['16_0_beta1'] = 'ZenTao16.0.beta1';
$lang->group->versions['15_8'] = 'ZenTao15.8';
$lang->group->versions['15_7'] = 'ZenTao15.7';
$lang->group->versions['15_0_rc1'] = 'ZenTao15.0.rc1';
$lang->group->versions['12_5'] = 'ZenTao12.5';
$lang->group->versions['12_3'] = 'ZenTao12.3';
$lang->group->versions['11_6_2'] = 'ZenTao11.6.2';
$lang->group->versions['10_6'] = 'ZenTao10.6';
$lang->group->versions['10_1'] = 'ZenTao10.1';
$lang->group->versions['10_0_alpha'] = 'ZenTao10.0.alpha';
$lang->group->versions['9_8'] = 'ZenTao9.8';
$lang->group->versions['9_6'] = 'ZenTao9.6';
$lang->group->versions['9_5'] = 'ZenTao9.5';
$lang->group->versions['9_2'] = 'ZenTao9.2';
$lang->group->versions['9_1'] = 'ZenTao9.1';
$lang->group->versions['9_0'] = 'ZenTao9.0';
$lang->group->versions['8_4'] = 'ZenTao8.4';
$lang->group->versions['8_3'] = 'ZenTao8.3';
$lang->group->versions['8_2_beta'] = 'ZenTao8.2.beta';
$lang->group->versions['8_0_1'] = 'ZenTao8.0.1';
$lang->group->versions['8_0'] = 'ZenTao8.0';
$lang->group->versions['7_4_beta'] = 'ZenTao7.4.beta';
$lang->group->versions['7_3'] = 'ZenTao7.3';
$lang->group->versions['7_2'] = 'ZenTao7.2';
$lang->group->versions['7_1'] = 'ZenTao7.1';
$lang->group->versions['6_4'] = 'ZenTao6.4';
$lang->group->versions['6_3'] = 'ZenTao6.3';
$lang->group->versions['6_2'] = 'ZenTao6.2';
$lang->group->versions['6_1'] = 'ZenTao6.1';
$lang->group->versions['5_3'] = 'ZenTao5.3';
$lang->group->versions['5_1'] = 'ZenTao5.1';
$lang->group->versions['5_0_beta2'] = 'ZenTao5.0.beta2';
$lang->group->versions['5_0_beta1'] = 'ZenTao5.0.beta1';
$lang->group->versions['4_3_beta'] = 'ZenTao4.3.beta';
$lang->group->versions['4_2_beta'] = 'ZenTao4.2.beta';
$lang->group->versions['4_1'] = 'ZenTao4.1';
$lang->group->versions['4_0_1'] = 'ZenTao4.0.1';
$lang->group->versions['4_0'] = 'ZenTao4.0';
$lang->group->versions['4_0_beta2'] = 'ZenTao4.0.beta2';
$lang->group->versions['4_0_beta1'] = 'ZenTao4.0.beta1';
$lang->group->versions['3_3'] = 'ZenTao3.3';
$lang->group->versions['3_2_1'] = 'ZenTao3.2.1';
$lang->group->versions['3_2'] = 'ZenTao3.2';
$lang->group->versions['3_1'] = 'ZenTao3.1';
$lang->group->versions['3_0_beta2'] = 'ZenTao3.0.beta2';
$lang->group->versions['3_0_beta1'] = 'ZenTao3.0.beta1';
$lang->group->versions['2_4'] = 'ZenTao2.4';
$lang->group->versions['2_3'] = 'ZenTao2.3';
$lang->group->versions['2_2'] = 'ZenTao2.2';
$lang->group->versions['2_1'] = 'ZenTao2.1';
$lang->group->versions['2_0'] = 'ZenTao2.0';
$lang->group->versions['1_5'] = 'ZenTao1.5';
$lang->group->versions['1_4'] = 'ZenTao1.4';
$lang->group->versions['1_3'] = 'ZenTao1.3';
$lang->group->versions['1_2'] = 'ZenTao1.2';
$lang->group->versions['1_1'] = 'ZenTao1.1';
$lang->group->versions['1_0_1'] = 'ZenTao1.0.1';
include (dirname(__FILE__) . '/resource.php');
+1 -1
View File
@@ -2065,7 +2065,6 @@ $lang->resource->workestimation = new stdclass();
$lang->resource->gapanalysis = new stdclass();
$lang->resource->executionview = new stdclass();
$lang->resource->managespace = new stdclass();
$lang->resource->managespace = new stdclass();
$lang->resource->systemteam = new stdclass();
$lang->resource->systemschedule = new stdclass();
$lang->resource->systemeffort = new stdclass();
@@ -2115,6 +2114,7 @@ if(!$inUpgrade)
{
unset($lang->resource->program);
unset($lang->resource->project->programTitle);
unset($lang->resource->product->manageLine);
}
if(!helper::hasFeature('waterfall') and !helper::hasFeature('waterfallplus'))
{
+81 -81
View File
@@ -121,86 +121,86 @@ $lang->privpackage->belong = '所属权限包';
$lang->group->copyOptions['copyPriv'] = '复制权限';
$lang->group->copyOptions['copyUser'] = '复制用户';
$lang->group->versions[''] = '修改历史';
$lang->group->versions['18_4'] = '禅道18.4';
$lang->group->versions['18_3'] = '禅道18.3';
$lang->group->versions['18_2'] = '禅道18.2';
$lang->group->versions['18_1'] = '禅道18.1';
$lang->group->versions['18_0'] = '禅道18.0';
$lang->group->versions['18_0_beta3'] = '禅道18.0.beta3';
$lang->group->versions['18_0_beta2'] = '禅道18.0.beta2';
$lang->group->versions['18_0_beta1'] = '禅道18.0.beta1';
$lang->group->versions['17_6_2'] = '禅道17.6.2';
$lang->group->versions['17_6'] = '禅道17.6';
$lang->group->versions['17_5'] = '禅道17.5';
$lang->group->versions['17_4'] = '禅道17.4';
$lang->group->versions['17_3'] = '禅道17.3';
$lang->group->versions['17_2'] = '禅道17.2';
$lang->group->versions['17_1'] = '禅道17.1';
$lang->group->versions['17_0_beta2'] = '禅道17.0.beta2';
$lang->group->versions['17_0_beta1'] = '禅道17.0.beta1';
$lang->group->versions['16_5_beta1'] = '禅道16.5.beta1';
$lang->group->versions['16_4'] = '禅道16.4';
$lang->group->versions['16_3'] = '禅道16.3';
$lang->group->versions['16_2'] = '禅道16.2';
$lang->group->versions['16_1'] = '禅道16.1';
$lang->group->versions['16_0'] = '禅道16.0';
$lang->group->versions['16_0_beta1'] = '禅道16.0.beta1';
$lang->group->versions['15_8'] = '禅道15.8';
$lang->group->versions['15_7'] = '禅道15.7';
$lang->group->versions['15_0_rc1'] = '禅道15.0.rc1';
$lang->group->versions['12_5'] = '禅道12.5';
$lang->group->versions['12_3'] = '禅道12.3';
$lang->group->versions['11_6_2'] = '禅道11.6.2';
$lang->group->versions['10_6'] = '禅道10.6';
$lang->group->versions['10_1'] = '禅道10.1';
$lang->group->versions['10_0_alpha'] = '禅道10.0.alpha';
$lang->group->versions['9_8'] = '禅道9.8';
$lang->group->versions['9_6'] = '禅道9.6';
$lang->group->versions['9_5'] = '禅道9.5';
$lang->group->versions['9_2'] = '禅道9.2';
$lang->group->versions['9_1'] = '禅道9.1';
$lang->group->versions['9_0'] = '禅道9.0';
$lang->group->versions['8_4'] = '禅道8.4';
$lang->group->versions['8_3'] = '禅道8.3';
$lang->group->versions['8_2_beta'] = '禅道8.2.beta';
$lang->group->versions['8_0_1'] = '禅道8.0.1';
$lang->group->versions['8_0'] = '禅道8.0';
$lang->group->versions['7_4_beta'] = '禅道7.4.beta';
$lang->group->versions['7_3'] = '禅道7.3';
$lang->group->versions['7_2'] = '禅道7.2';
$lang->group->versions['7_1'] = '禅道7.1';
$lang->group->versions['6_4'] = '禅道6.4';
$lang->group->versions['6_3'] = '禅道6.3';
$lang->group->versions['6_2'] = '禅道6.2';
$lang->group->versions['6_1'] = '禅道6.1';
$lang->group->versions['5_3'] = '禅道5.3';
$lang->group->versions['5_1'] = '禅道5.1';
$lang->group->versions['5_0_beta2'] = '禅道5.0.beta2';
$lang->group->versions['5_0_beta1'] = '禅道5.0.beta1';
$lang->group->versions['4_3_beta'] = '禅道4.3.beta';
$lang->group->versions['4_2_beta'] = '禅道4.2.beta';
$lang->group->versions['4_1'] = '禅道4.1';
$lang->group->versions['4_0_1'] = '禅道4.0.1';
$lang->group->versions['4_0'] = '禅道4.0';
$lang->group->versions['4_0_beta2'] = '禅道4.0.beta2';
$lang->group->versions['4_0_beta1'] = '禅道4.0.beta1';
$lang->group->versions['3_3'] = '禅道3.3';
$lang->group->versions['3_2_1'] = '禅道3.2.1';
$lang->group->versions['3_2'] = '禅道3.2';
$lang->group->versions['3_1'] = '禅道3.1';
$lang->group->versions['3_0_beta2'] = '禅道3.0.beta2';
$lang->group->versions['3_0_beta1'] = '禅道3.0.beta1';
$lang->group->versions['2_4'] = '禅道2.4';
$lang->group->versions['2_3'] = '禅道2.3';
$lang->group->versions['2_2'] = '禅道2.2';
$lang->group->versions['2_1'] = '禅道2.1';
$lang->group->versions['2_0'] = '禅道2.0';
$lang->group->versions['1_5'] = '禅道1.5';
$lang->group->versions['1_4'] = '禅道1.4';
$lang->group->versions['1_3'] = '禅道1.3';
$lang->group->versions['1_2'] = '禅道1.2';
$lang->group->versions['1_1'] = '禅道1.1';
$lang->group->versions['1_0_1'] = '禅道1.0.1';
$lang->group->versions[''] = '修改历史';
$lang->group->versions['18_4_alpha1'] = '禅道18.4.alpha1';
$lang->group->versions['18_3'] = '禅道18.3';
$lang->group->versions['18_2'] = '禅道18.2';
$lang->group->versions['18_1'] = '禅道18.1';
$lang->group->versions['18_0'] = '禅道18.0';
$lang->group->versions['18_0_beta3'] = '禅道18.0.beta3';
$lang->group->versions['18_0_beta2'] = '禅道18.0.beta2';
$lang->group->versions['18_0_beta1'] = '禅道18.0.beta1';
$lang->group->versions['17_6_2'] = '禅道17.6.2';
$lang->group->versions['17_6'] = '禅道17.6';
$lang->group->versions['17_5'] = '禅道17.5';
$lang->group->versions['17_4'] = '禅道17.4';
$lang->group->versions['17_3'] = '禅道17.3';
$lang->group->versions['17_2'] = '禅道17.2';
$lang->group->versions['17_1'] = '禅道17.1';
$lang->group->versions['17_0_beta2'] = '禅道17.0.beta2';
$lang->group->versions['17_0_beta1'] = '禅道17.0.beta1';
$lang->group->versions['16_5_beta1'] = '禅道16.5.beta1';
$lang->group->versions['16_4'] = '禅道16.4';
$lang->group->versions['16_3'] = '禅道16.3';
$lang->group->versions['16_2'] = '禅道16.2';
$lang->group->versions['16_1'] = '禅道16.1';
$lang->group->versions['16_0'] = '禅道16.0';
$lang->group->versions['16_0_beta1'] = '禅道16.0.beta1';
$lang->group->versions['15_8'] = '禅道15.8';
$lang->group->versions['15_7'] = '禅道15.7';
$lang->group->versions['15_0_rc1'] = '禅道15.0.rc1';
$lang->group->versions['12_5'] = '禅道12.5';
$lang->group->versions['12_3'] = '禅道12.3';
$lang->group->versions['11_6_2'] = '禅道11.6.2';
$lang->group->versions['10_6'] = '禅道10.6';
$lang->group->versions['10_1'] = '禅道10.1';
$lang->group->versions['10_0_alpha'] = '禅道10.0.alpha';
$lang->group->versions['9_8'] = '禅道9.8';
$lang->group->versions['9_6'] = '禅道9.6';
$lang->group->versions['9_5'] = '禅道9.5';
$lang->group->versions['9_2'] = '禅道9.2';
$lang->group->versions['9_1'] = '禅道9.1';
$lang->group->versions['9_0'] = '禅道9.0';
$lang->group->versions['8_4'] = '禅道8.4';
$lang->group->versions['8_3'] = '禅道8.3';
$lang->group->versions['8_2_beta'] = '禅道8.2.beta';
$lang->group->versions['8_0_1'] = '禅道8.0.1';
$lang->group->versions['8_0'] = '禅道8.0';
$lang->group->versions['7_4_beta'] = '禅道7.4.beta';
$lang->group->versions['7_3'] = '禅道7.3';
$lang->group->versions['7_2'] = '禅道7.2';
$lang->group->versions['7_1'] = '禅道7.1';
$lang->group->versions['6_4'] = '禅道6.4';
$lang->group->versions['6_3'] = '禅道6.3';
$lang->group->versions['6_2'] = '禅道6.2';
$lang->group->versions['6_1'] = '禅道6.1';
$lang->group->versions['5_3'] = '禅道5.3';
$lang->group->versions['5_1'] = '禅道5.1';
$lang->group->versions['5_0_beta2'] = '禅道5.0.beta2';
$lang->group->versions['5_0_beta1'] = '禅道5.0.beta1';
$lang->group->versions['4_3_beta'] = '禅道4.3.beta';
$lang->group->versions['4_2_beta'] = '禅道4.2.beta';
$lang->group->versions['4_1'] = '禅道4.1';
$lang->group->versions['4_0_1'] = '禅道4.0.1';
$lang->group->versions['4_0'] = '禅道4.0';
$lang->group->versions['4_0_beta2'] = '禅道4.0.beta2';
$lang->group->versions['4_0_beta1'] = '禅道4.0.beta1';
$lang->group->versions['3_3'] = '禅道3.3';
$lang->group->versions['3_2_1'] = '禅道3.2.1';
$lang->group->versions['3_2'] = '禅道3.2';
$lang->group->versions['3_1'] = '禅道3.1';
$lang->group->versions['3_0_beta2'] = '禅道3.0.beta2';
$lang->group->versions['3_0_beta1'] = '禅道3.0.beta1';
$lang->group->versions['2_4'] = '禅道2.4';
$lang->group->versions['2_3'] = '禅道2.3';
$lang->group->versions['2_2'] = '禅道2.2';
$lang->group->versions['2_1'] = '禅道2.1';
$lang->group->versions['2_0'] = '禅道2.0';
$lang->group->versions['1_5'] = '禅道1.5';
$lang->group->versions['1_4'] = '禅道1.4';
$lang->group->versions['1_3'] = '禅道1.3';
$lang->group->versions['1_2'] = '禅道1.2';
$lang->group->versions['1_1'] = '禅道1.1';
$lang->group->versions['1_0_1'] = '禅道1.0.1';
include (dirname(__FILE__) . '/resource.php');
+22 -17
View File
@@ -469,10 +469,11 @@ class groupModel extends model
$privs[] = $data;
}
}
$this->insertPrivs($privs);
$depentedPrivs = $this->getPrivByIdList($depentedPrivs);
foreach($depentedPrivs as $privID => $priv)
{
if(empty($_POST['actions'][$priv->module]) or in_array($priv->method, $_POST['actions'][$priv->module]))
if(!empty($_POST['actions'][$priv->module]) and in_array($priv->method, $_POST['actions'][$priv->module]))
{
unset($depentedPrivs[$privID]);
continue;
@@ -483,7 +484,7 @@ class groupModel extends model
$data->method = $priv->method;
$this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec();
}
$recommendPrivs = $this->getPrivByIdList(zget($_POST, 'recommendPrivs'));
$recommendPrivs = $this->getPrivByIdList(zget($_POST, 'recommendPrivs', '0'));
foreach($recommendPrivs as $privID => $priv)
{
if(in_array($priv->method, zget($_POST['actions'], $priv->module, array())))
@@ -497,7 +498,6 @@ class groupModel extends model
$data->method = $priv->method;
$this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec();
}
$this->insertPrivs($privs);
}
return !empty($depentedPrivs) ? true : false;
}
@@ -1511,7 +1511,7 @@ class groupModel extends model
if(empty($lang)) $lang = $this->app->getClientLang();
return $this->dao->select('t1.*,t2.key,t2.value,t2.desc')->from(TABLE_PRIV)->alias('t1')
->leftJoin(TABLE_PRIVLANG)->alias('t2')->on('t1.id=t2.objectID')
->where('t1.id')->eq($privID)
->where('t1.id')->eq((int)$privID)
->andWhere('t2.objectType')->eq('priv')
->andWhere('t2.lang')->eq($lang)
->fetch();
@@ -1604,9 +1604,8 @@ class groupModel extends model
{
$modules = $this->getPrivManagerPairs('module', $view);
$modules = array_keys($modules);
$modules = implode(',', $modules);
$privs = $this->dao->select("t1.id, t1.module, t1.method, CONCAT(t1.module, '-', t1.method) AS action, IF(t3.type = 'module', 0, t1.parent) as parent, t1.order, t2.`key`, t2.`value`, t2.desc, IF(t3.type = 'module', t3.code, t4.code) as parentCode, IF(t3.type = 'module', 999, INSTR('$modules', t4.code)) as moduleOrder")->from(TABLE_PRIV)->alias('t1')
$privs = $this->dao->select("t1.id, t1.module, t1.method, CONCAT(t1.module, '-', t1.method) AS action, IF(t3.type = 'module', 0, t1.parent) as parent, t1.order, t2.`key`, t2.`value`, t2.desc, IF(t3.type = 'module', t3.code, t4.code) as parentCode")->from(TABLE_PRIV)->alias('t1')
->leftJoin(TABLE_PRIVLANG)->alias('t2')->on('t1.id=t2.objectID')
->leftJoin(TABLE_PRIVMANAGER)->alias('t3')->on('t1.parent=t3.id')
->leftJoin(TABLE_PRIVMANAGER)->alias('t4')->on('t3.parent=t4.id')
@@ -1625,10 +1624,12 @@ class groupModel extends model
->markRight(2)
->andWhere('t1.edition')->like("%,{$this->config->edition},%")
->andWhere('t1.vision')->like("%,{$this->config->vision},%")
->orderBy("moduleOrder asc, t3.order asc, `order` asc")
->orderBy("t3.order asc, `order` asc")
->page($pager)
->fetchAll('action');
return $privs;
->fetchGroup('parentCode', 'action');
$privList = array(); foreach($modules as $module) $privList = array_merge($privList, zget($privs, $module, array()));
return $privList;
}
/**
@@ -2122,8 +2123,8 @@ class groupModel extends model
else
{
list($moduleName, $methodLang) = explode('-', $priv->key);
if($moduleName == 'requirement') $moduleName = 'story';
$this->app->loadLang($moduleName);
$actualModule = $moduleName == 'requirement' ? 'story' : $moduleName;
$this->app->loadLang($actualModule);
$hasLang = (!empty($moduleName) and !empty($methodLang) and isset($this->lang->resource->{$priv->module}) and isset($this->lang->resource->{$priv->module}->{$priv->method}));
if(!$hasLang)
@@ -2160,6 +2161,7 @@ class groupModel extends model
{
$key = "{$module}-{$method}";
$priv = new stdclass();
$priv->id = $key;
$priv->module = $module;
$priv->method = $method;
$priv->action = $key;
@@ -2182,6 +2184,7 @@ class groupModel extends model
$key = "{$module}-{$method}";
$priv = new stdclass();
$priv->id = $key;
$priv->module = $module;
$priv->method = $method;
$priv->action = $key;
@@ -2211,8 +2214,7 @@ class groupModel extends model
{
$modulePairs = $this->getPrivManagerPairs('module');
$modules = array_keys($modulePairs);
$modules = implode(',', $modules);
$relatedPrivs = $this->dao->select("t1.relationPriv,t1.type,t2.parent,t2.module,t2.method,t2.`order`,t3.`key`,t3.value, IF(t4.type = 'module', 999, INSTR('$modules', t5.code)) as moduleOrder")->from(TABLE_PRIVRELATION)->alias('t1')
$privs = $this->dao->select("t1.relationPriv,t1.type,t2.parent,t2.module,t2.method,t2.`order`,t3.`key`,t3.value, IF(t4.type = 'module', t4.code, t5.code) as parentCode")->from(TABLE_PRIVRELATION)->alias('t1')
->leftJoin(TABLE_PRIV)->alias('t2')->on('t1.relationPriv=t2.id')
->leftJoin(TABLE_PRIVLANG)->alias('t3')->on('t1.relationPriv=t3.objectID')
->leftJoin(TABLE_PRIVMANAGER)->alias('t4')->on('t2.parent=t4.id')
@@ -2240,8 +2242,11 @@ class groupModel extends model
->andWhere('t5.type')->eq('view')
->beginIF(!empty($view) and $view != 'general')->andWhere('t1.module')->in($modules)->fi()
->markRight(2)
->orderBy('moduleOrder asc, t2.`order`_asc, t1.`type` desc')
->fetchAll('relationPriv');
->orderBy('t2.`order`_asc, t1.`type` desc')
->fetchGroup('parentCode', 'relationPriv');
$relatedPrivs = array();
foreach($modules as $module) $relatedPrivs = array_merge($relatedPrivs, zget($privs, $module, array()));
$privList = empty($type) ? array('depend' => array(), 'recommend' => array()) : array($type => array());
if(empty($relatedPrivs)) return $privList;
@@ -2249,13 +2254,13 @@ class groupModel extends model
$managerList = $this->dao->select('*')->from(TABLE_PRIVMANAGER)->fetchAll('id');
$relatedPrivs = $this->transformPrivLang($relatedPrivs);
foreach($relatedPrivs as $privID => $relatedPriv)
foreach($relatedPrivs as $relatedPriv)
{
$module = $managerList[$relatedPriv->parent]->type == 'package' ? $managerList[$managerList[$relatedPriv->parent]->parent]->code : $managerList[$relatedPriv->parent]->code;
if(!isset($privList[$relatedPriv->type][$module])) $privList[$relatedPriv->type][$module] = array();
$privList[$relatedPriv->type][$module]['title'] = $modulePairs[$module];
$privList[$relatedPriv->type][$module]['id'] = $relatedPriv->parent;
$privList[$relatedPriv->type][$module]['children'][] = array('title' => $relatedPriv->name, 'relationPriv' => $privID, 'parent' => $relatedPriv->parent, 'module' => $relatedPriv->module, 'method' => $relatedPriv->method);
$privList[$relatedPriv->type][$module]['children'][] = array('title' => $relatedPriv->name, 'relationPriv' => $relatedPriv->relationPriv, 'parent' => $relatedPriv->parent, 'module' => $relatedPriv->module, 'method' => $relatedPriv->method);
}
if(empty($type) or $type == 'depend') $privList['depend'] = array_values($privList['depend']);
+1 -1
View File
@@ -54,7 +54,7 @@
<?php echo "<button class='btn disabled'><i class='icon icon-copy disabled' title='{$lang->group->copy}'></i></button>";?>
<?php else:?>
<?php common::printIcon('group', 'manageView', "groupID=$group->id", $group, 'list', 'eye');?>
<?php common::printIcon('group', 'managepriv', "type=byGroup&param=$group->id", $group, 'list', 'lock');?>
<?php common::printIcon('group', 'managepriv', "type=byPackage&param=$group->id", $group, 'list', 'lock');?>
<?php common::printIcon('group', 'manageMember', "groupID=$group->id", $group, 'list', 'persons', '', "iframe", true, "data-width='90%'");?>
<?php common::printIcon('group', 'edit', "groupID=$group->id", $group, 'list', '', '', "iframe", true, "data-width='550'");?>
<?php common::printIcon('group', 'copy', "groupID=$group->id", $group, 'list', '', '', "iframe", true, "data-width='550'");?>
+2 -2
View File
@@ -80,8 +80,8 @@
<div id='mainContainer'>
<div class='main main-content'>
<div class="btn-group">
<?php echo html::a(inlink('managePriv', "type=byGroupbyPackage&param=$groupID&menu=$menu&version=$version"), "<i class='icon-without-authority-pack'></i>", '', "class='btn btn-icon switchBtn text-primary'");?>
<?php echo html::a(inlink('managePriv', "type=byPackage&param=$groupID&menu=$menu&version=$version"), "<i class='icon-has-authority-pack'></i>", '', "class='btn btn-icon switchBtn'");?>
<?php echo html::a(inlink('managePriv', "type=byGroup&param=$groupID&menu=$menu&version=$version"), "<i class='icon-without-authority-pack'></i>", '', "class='btn btn-icon switchBtn text-primary'");?>
</div>
<table class='table table-hover table-striped table-bordered' id='privList'>
<thead>
@@ -216,7 +216,7 @@ $(document).ready(function()
$('.menus .icon-plus').click(function()
{
$(this).toggleClass('icon-minus', 'icon-plus');
$('.menus input[name^=actions]:not(input[value=browse])').parent('.checkbox-primary').toggle();
$(this).closest('.menus').find('input[name^=actions]:not(input[value=browse])').parent('.checkbox-primary').toggle();
})
/**
+1 -1
View File
@@ -80,8 +80,8 @@
<div id='mainContainer'>
<div class='main main-content'>
<div class="btn-group">
<?php echo html::a(inlink('managePriv', "type=byGroup&param=$groupID&menu=$menu&version=$version"), "<i class='icon-without-authority-pack'></i>", '', "class='btn btn-icon switchBtn'");?>
<?php echo html::a(inlink('managePriv', "type=byPackage&param=$groupID&menu=$menu&version=$version"), "<i class='icon-has-authority-pack'></i>", '', "class='btn btn-icon switchBtn text-primary'");?>
<?php echo html::a(inlink('managePriv', "type=byGroup&param=$groupID&menu=$menu&version=$version"), "<i class='icon-without-authority-pack'></i>", '', "class='btn btn-icon switchBtn'");?>
</div>
<table class='table table-hover table-striped table-bordered' id='privPackageList'>
<thead>
+5 -3
View File
@@ -270,7 +270,9 @@ class install extends control
if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') $httpType = 'https';
if(isset($_SERVER['REQUEST_SCHEME']) and strtolower($_SERVER['REQUEST_SCHEME']) == 'https') $httpType = 'https';
if(strpos($this->app->getClientLang(), 'zh') === 0) $this->loadModel('api')->createDemoData($this->lang->api->zentaoAPI, "{$httpType}://{$_SERVER['HTTP_HOST']}" . $this->app->config->webRoot . 'api.php/v1', '16.0');
$this->loadModel('upgrade')->createDefaultDimension();
if($this->config->edition != 'open') $this->loadModel('upgrade')->processDataset();
return print(js::locate(inlink('step6'), 'parent'));
}
@@ -299,9 +301,9 @@ class install extends control
$canDelFile = is_writable($this->app->getAppRoot() . 'www');
$installFile = $this->app->getAppRoot() . 'www/install.php';
$upgradeFile = $this->app->getAppRoot() . 'www/upgrade.php';
$installFileDeleted = $canDelFile && is_writable($installFile) ? unlink($installFile) : false;
$installFileDeleted = ($canDelFile and file_exists($installFile)) ? unlink($installFile) : false;
if($canDelFile and is_writable($upgradeFile)) unlink($upgradeFile);
if($canDelFile and file_exists($upgradeFile)) unlink($upgradeFile);
unset($_SESSION['installing']);
session_destroy();
+4
View File
@@ -31,10 +31,14 @@
<th><?php echo $lang->install->defaultLang;?></th>
<td><?php echo html::select('defaultLang', $config->langs, $app->getClientLang(), "class='form-control'");?></td><td></td>
</tr>
<?php if($config->edition != 'open'):?>
<tr>
<th><?php echo $lang->install->dbDriver;?></th>
<td><?php echo html::select('dbDriver', $lang->install->dbDriverList, 'mysql', "class='form-control'");?></td><td></td>
</tr>
<?php else:?>
<?php echo html::hidden('dbDriver', 'mysql');?>
<?php endif;?>
<tr>
<th><?php echo $lang->install->dbHost;?></th>
<td><?php echo html::input('dbHost', $dbHost, "class='form-control'");?></td>
+2 -2
View File
@@ -3705,7 +3705,7 @@ class kanbanModel extends model
public function getColumnsByObject($objectType = '', $objectID = 0, $archived = 0, $deleted = '0')
{
return $this->dao->select('*')->from(TABLE_KANBANCOLUMN)
->where(true)
->where('1=1')
->beginIF($objectType)->andWhere($objectType)->eq($objectID)->fi()
->beginIF($archived != '')->andWhere('archived')->eq($archived)->fi()
->beginIF($deleted != '')->andWhere('deleted')->eq($deleted)->fi()
@@ -3817,7 +3817,7 @@ class kanbanModel extends model
public function getCardsByObject($objectType = '', $objectID = 0, $archived = '0', $deleted = '0')
{
return $this->dao->select('*')->from(TABLE_KANBANCARD)
->where(true)
->where('1=1')
->beginIF($objectType)->andWhere($objectType)->eq($objectID)->fi()
->beginIF($archived != '')->andWhere('archived')->eq($archived)->fi()
->beginIF($deleted != '')->andWhere('deleted')->eq($deleted)->fi()
+1 -1
View File
@@ -202,7 +202,7 @@ $lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
/* Release Detail. */
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => '', 'desc' => '');
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => 'We have enhanced the interaction experience of permissions and documents, while introducing the concept of test scenarios. Moreover, we now provide support for importing use cases with XMIND. Additionally, we have fully revamped the BI module by incorporating large screens, pivot tables, charts, and data capabilities.', 'desc' => '');
$lang->misc->feature->all['18.3'][] = array('title' => 'Language item customization is added in secondary development, which supports the definition of language items for menus and search tags; Editor functionality is added in the secondary development, which allows users to turn it on and off on demand; The forms could be saved temporarily when users exits unexpectedly, and the unsaved information will be filled automatically the next time you enter.', 'desc' => '');
$lang->misc->feature->all['18.2'][] = array('title' => 'Agile Plus and Waterfall Plus management models are newly added. Support for unlimited splitting of waterfall project stages. The UI of Admin is completely upgraded and redesigned. Fix bugs.', 'desc' => '');
$lang->misc->feature->all['18.1'][] = array('title' => 'The automation testing solution interaction is optimized, while a new snapshot management function is newly added. ZenTao IM implemented online collaboration of PPT documents.Fix bugs.', 'desc' => '');
+1 -1
View File
@@ -202,7 +202,7 @@ $lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
/* Release Detail. */
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => '', 'desc' => '');
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => 'We have enhanced the interaction experience of permissions and documents, while introducing the concept of test scenarios. Moreover, we now provide support for importing use cases with XMIND. Additionally, we have fully revamped the BI module by incorporating large screens, pivot tables, charts, and data capabilities.', 'desc' => '');
$lang->misc->feature->all['18.3'][] = array('title' => 'Language item customization is added in secondary development, which supports the definition of language items for menus and search tags; Editor functionality is added in the secondary development, which allows users to turn it on and off on demand; The forms could be saved temporarily when users exits unexpectedly, and the unsaved information will be filled automatically the next time you enter.', 'desc' => '');
$lang->misc->feature->all['18.2'][] = array('title' => 'Agile Plus and Waterfall Plus management models are newly added. Support for unlimited splitting of waterfall project stages. The UI of Admin is completely upgraded and redesigned. Fix bugs.', 'desc' => '');
$lang->misc->feature->all['18.1'][] = array('title' => 'The automation testing solution interaction is optimized, while a new snapshot management function is newly added. ZenTao IM implemented online collaboration of PPT documents.Fix bugs.', 'desc' => '');
+1 -1
View File
@@ -202,7 +202,7 @@ $lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
/* Release Detail. */
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => '', 'desc' => '');
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => 'We have enhanced the interaction experience of permissions and documents, while introducing the concept of test scenarios. Moreover, we now provide support for importing use cases with XMIND. Additionally, we have fully revamped the BI module by incorporating large screens, pivot tables, charts, and data capabilities.', 'desc' => '');
$lang->misc->feature->all['18.3'][] = array('title' => 'Language item customization is added in secondary development, which supports the definition of language items for menus and search tags; Editor functionality is added in the secondary development, which allows users to turn it on and off on demand; The forms could be saved temporarily when users exits unexpectedly, and the unsaved information will be filled automatically the next time you enter.', 'desc' => '');
$lang->misc->feature->all['18.2'][] = array('title' => 'Agile Plus and Waterfall Plus management models are newly added. Support for unlimited splitting of waterfall project stages. The UI of Admin is completely upgraded and redesigned. Fix bugs.', 'desc' => '');
$lang->misc->feature->all['18.1'][] = array('title' => 'The automation testing solution interaction is optimized, while a new snapshot management function is newly added. ZenTao IM implemented online collaboration of PPT documents.Fix bugs.', 'desc' => '');
+1 -1
View File
@@ -202,7 +202,7 @@ $lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
/* Release Detail. */
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => '', 'desc' => '');
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => '优化权限、文档交互体验,测试新增场景概念,用例支持xmind导入,并对BI模块中的大屏、透视表、图表、数据表进行了全面升级。', 'desc' => '');
$lang->misc->feature->all['18.3'][] = array('title' => '二次开发增加语言项自定义,支持对菜单和检索标签的语言项进行定义;二次开发增加编辑器功能,支持用户按需开启和关闭;表单意外退出支持表单暂存,下次进入自动代入填写的未保存信息。', 'desc' => '');
$lang->misc->feature->all['18.2'][] = array('title' => '新增融合敏捷、融合瀑布管理模型,瀑布项目阶段支持无限级拆分,后台进行全新UI改版。修复Bug。', 'desc' => '');
$lang->misc->feature->all['18.1'][] = array('title' => '自动化测试解决方案交互优化、新增快照管理功能。禅道客户端实现了 PPT文档在线协作。修复Bug。', 'desc' => '');
+1 -1
View File
@@ -17,7 +17,7 @@ $lang->my->story = 'My Stories';
$lang->my->doc = "My Docs";
$lang->my->createProgram = 'Create Program';
$lang->my->project = "My {$lang->projectCommon}s";
$lang->my->execution = "My {$lang->executionCommon}s";
$lang->my->execution = "My {$lang->execution->common}s";
$lang->my->audit = 'Review';
$lang->my->issue = 'My Issues';
$lang->my->risk = 'My Risks';
+1 -1
View File
@@ -17,7 +17,7 @@ $lang->my->story = 'My Stories';
$lang->my->doc = "My Docs";
$lang->my->createProgram = 'Create Program';
$lang->my->project = "My {$lang->projectCommon}s";
$lang->my->execution = "My {$lang->executionCommon}s";
$lang->my->execution = "My {$lang->execution->common}s";
$lang->my->audit = 'Review';
$lang->my->issue = 'My Issues';
$lang->my->risk = 'My Risks';
+1 -1
View File
@@ -17,7 +17,7 @@ $lang->my->story = 'My Stories';
$lang->my->doc = "My Docs";
$lang->my->createProgram = 'Create Program';
$lang->my->project = "My {$lang->projectCommon}s";
$lang->my->execution = "My {$lang->executionCommon}s";
$lang->my->execution = "My {$lang->execution->common}s";
$lang->my->audit = 'Review';
$lang->my->issue = 'My Issues';
$lang->my->risk = 'My Risks';
+1 -1
View File
@@ -17,7 +17,7 @@ $lang->my->story = "我的{$lang->SRCommon}";
$lang->my->doc = "我的文档";
$lang->my->createProgram = '添加' . $lang->projectCommon;
$lang->my->project = '我的' . $lang->projectCommon;
$lang->my->execution = "我的{$lang->executionCommon}";
$lang->my->execution = "我的{$lang->execution->common}";
$lang->my->audit = '审批';
$lang->my->issue = '我的问题';
$lang->my->risk = '我的风险';
+91
View File
@@ -1,2 +1,93 @@
<?php
$config->pivot = new stdclass();
$config->pivot->widthInput = 128;
$config->pivot->widthDate = 248;
$config->pivot->fileType = array('xlsx' => 'xlsx', 'xls' => 'xls', 'html' => 'html', 'mht' => 'mht');
$config->pivot->create = new stdclass();
$config->pivot->create->requiredFields = 'type,group';
$config->pivot->edit = new stdclass();
$config->pivot->edit->requiredFields = 'type,group';
$config->pivot->design = new stdclass();
$config->pivot->design->requiredFields = 'group';
$config->pivot->multiColumn = array('cluBarX' => 'yaxis', 'cluBarY' => 'yaxis', 'radar' => 'yaxis', 'line' => 'yaxis', 'stackedBar' => 'yaxis', 'stackedBarY' => 'yaxis');
$config->pivot->checkForm = array();
$config->pivot->checkForm['line'] = array('cantequal' => 'xaxis,yaxis');
$config->pivot->checkForm['cluBarX'] = array('cantequal' => 'xaxis,yaxis');
$config->pivot->checkForm['cluBarY'] = array('cantequal' => 'xaxis,yaxis');
$config->pivot->checkForm['radar'] = array('cantequal' => 'xaxis,yaxis');
$config->pivot->checkForm['stackedBar'] = array('cantequal' => 'xaxis,yaxis');
$config->pivot->checkForm['stackedBarY'] = array('cantequal' => 'xaxis,yaxis');
global $lang;
$config->pivot->settings = array();
$config->pivot->settings['cluBarX'] = array();
$config->pivot->settings['cluBarX']['xaxis'] = array();
$config->pivot->settings['cluBarX']['xaxis'][] = array('field' => 'xaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 4);
$config->pivot->settings['cluBarX']['yaxis'] = array();
$config->pivot->settings['cluBarX']['yaxis'][] = array('field' => 'yaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
$config->pivot->settings['cluBarX']['yaxis'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
$config->pivot->settings['cluBarY'] = array();
$config->pivot->settings['cluBarY']['xaxis'] = array();
$config->pivot->settings['cluBarY']['xaxis'][] = array('field' => 'xaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 4);
$config->pivot->settings['cluBarY']['yaxis'] = array();
$config->pivot->settings['cluBarY']['yaxis'][] = array('field' => 'yaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
$config->pivot->settings['cluBarY']['yaxis'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
$config->pivot->settings['stackedBarY'] = array();
$config->pivot->settings['stackedBarY']['xaxis'] = array();
$config->pivot->settings['stackedBarY']['xaxis'][] = array('field' => 'xaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 4);
$config->pivot->settings['stackedBarY']['yaxis'] = array();
$config->pivot->settings['stackedBarY']['yaxis'][] = array('field' => 'yaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
$config->pivot->settings['stackedBarY']['yaxis'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
$config->pivot->settings['line'] = array();
$config->pivot->settings['line']['xaxis'] = array();
$config->pivot->settings['line']['xaxis'][] = array('field' => 'xaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 4);
$config->pivot->settings['line']['yaxis'] = array();
$config->pivot->settings['line']['yaxis'][] = array('field' => 'yaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
$config->pivot->settings['line']['yaxis'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
$config->pivot->settings['pie'] = array();
$config->pivot->settings['pie']['group'] = array();
$config->pivot->settings['pie']['group'][] = array('field' => 'group', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
$config->pivot->settings['pie']['metric'] = array();
$config->pivot->settings['pie']['metric'][] = array('field' => 'metric', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
$config->pivot->settings['pie']['stat'] = array();
$config->pivot->settings['pie']['stat'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
$config->pivot->settings['radar'] = array();
$config->pivot->settings['radar']['xaxis'] = array();
$config->pivot->settings['radar']['xaxis'][] = array('field' => 'xaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 4);
$config->pivot->settings['radar']['yaxis'] = array();
$config->pivot->settings['radar']['yaxis'][] = array('field' => 'yaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
$config->pivot->settings['radar']['yaxis'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
$config->pivot->settings['stackedBar'] = array();
$config->pivot->settings['stackedBar']['xaxis'] = array();
$config->pivot->settings['stackedBar']['xaxis'][] = array('field' => 'xaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 4);
$config->pivot->settings['stackedBar']['yaxis'] = array();
$config->pivot->settings['stackedBar']['yaxis'][] = array('field' => 'yaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
$config->pivot->settings['stackedBar']['yaxis'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
$config->pivot->settings['testingReport'] = array('field' => array('type' => 'td'));
$config->pivot->transTypes = array();
$config->pivot->transTypes['int'] = 'number';
$config->pivot->transTypes['float'] = 'number';
$config->pivot->transTypes['double'] = 'number';
$config->pivot->transTypes['datetime'] = 'date';
$config->pivot->transTypes['date'] = 'date';
+55 -3
View File
@@ -68,10 +68,8 @@ class pivot extends control
if($pivot)
{
list($sql, $filterFormat) = $this->pivot->getFilterFormat($pivot->sql, $pivot->filters);
$pivot->sql = $sql;
$processSqlData = $this->loadModel('dataview')->getTables($sql);
$processSqlData = $this->loadModel('chart')->getTables($sql);
$sql = $processSqlData['sql'];
list($data, $configs) = $this->pivot->genSheet(json_decode(json_encode($pivot->fieldSettings), true), $pivot->settings, $sql, $filterFormat, json_decode($pivot->langs, true));
@@ -251,4 +249,58 @@ class pivot extends control
$this->view->submenu = 'staff';
$this->display();
}
/**
* Ajax get sys options.
*
* @param string $type
* @param string $object
* @param string $field
* @access public
* @return string
*/
public function ajaxGetSysOptions($type, $object = '', $field = '')
{
$sql = isset($_POST['sql']) ? $_POST['sql'] : '';
$filters = isset($_POST['filters']) ? $_POST['filters'] : '';
$sql = $this->loadModel('chart')->parseSqlVars($sql, $filters);
$options = $this->pivot->getSysOptions($type, $object, $field, $sql);
return print(html::select('default[]', array('' => '') + $options, '', "class='form-control form-select picker-select' multiple"));
}
/**
* Ajax get pivot table.
*
* @access public
* @return void
*/
public function ajaxGetPivot()
{
$post = fixer::input('post')->skipSpecial('settings,filters,sql,langs')->get();
$pivotID = $post->id;
$settings = $post->settings;
$filters = isset($_POST['searchFilters']) ? $_POST['searchFilters'] : (isset($_POST['filters']) ? $post->filters : array());
$filterType = 'result';
$pivot = $this->pivot->getById($pivotID);
list($sql, $filterFormat) = $this->pivot->getFilterFormat($post->sql, $filters);
$post->sql = $sql;
$settings['filterType'] = $filterType;
$sql = str_replace(';', '', "$post->sql");
$fields = $post->fieldSettings;
$langs = isset($post->langs) ? (is_array($post->langs) ? $post->langs : json_decode($post->langs, true)) : array();
$processSqlData = $this->loadModel('chart')->getTables($sql);
$sql = $processSqlData['sql'];
list($data, $configs) = $this->pivot->genSheet($fields, $settings, $sql, $filterFormat, $langs);
$this->pivot->buildPivotTable($data, $configs, $fields, $sql);
}
}
+10
View File
@@ -35,3 +35,13 @@ td .deviation {padding-left: 20px; text-align: left;}
.checkboxes {margin-bottom: 10px;}
.checkboxes .checkbox-primary {margin-bottom: 5px;}
.fixed-header-copy thead tr th {color: #fff !important;}
.table-panel {overflow-x: auto;}
.datatable {width: auto;}
.datatable th.header {line-height: 32px !important;}
.header-config {float: right; display: none;}
.header:hover .header-config {display: inline-block;}
.label-outline.label-info {border: unset; line-height: 14px;}
.border-bottom {border-bottom: 1px solid #f4f5f7;}
.text-center {text-align: center;}
.visibility-hidden{visibility: hidden;}
+15 -4
View File
@@ -1,6 +1,17 @@
#mainContent > .side-col.col-lg {width: 240px;}
.main-col .btn-toolbar {margin-bottom: 10px;}
.main-position {position: relative;}
.toolbar-padding {padding-right: 100px;}
.child-position {position: absolute; right: 0;}
#reportGroups .active {background-color: #e9f2fb; color: #006af1;}
.biz-version {padding-top: 10px;}
.biz-version a {color: #81511C;}
.parent-position {padding-right: 160px;}
.datagrid {overflow: auto;}
.heading-padding, .datagrid-padding {padding-left: 6px; padding-right: 6px;}
.filter-items > .table-row{display: table!important;}
.filter-items .filter-item:first-child {padding-left: 0!important;}
.filterBox {display: flex; margin-bottom: 20px; margin-left: 6px; margin-right: 6px;}
.filter-items {display: flex; flex: 1; flex-wrap: wrap;}
.filter-item {padding: 0 16px 5px 0;}
.filter-item-grow {flex-grow: 1;}
.queryBtn {display: flex; align-items: center; padding-bottom: 5px; flex-basis: 60px;}
.filter-item .picker-selections {width: 128px; overflow: hidden; text-overflow: clip; white-space: nowrap;}
#filterItems .picker-selections {overflow: hidden; text-overflow: clip; white-space: nowrap;}
+1 -1
View File
@@ -18,6 +18,6 @@ function changeParams(obj)
}
var params = window.btoa('begin=' + begin + '&end=' + end + '&product=' + product + '&execution=' + execution);
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + group + '&module=pivot&method=bugcreate&params=' + params);
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + groupID + '&module=pivot&method=bugcreate&params=' + params);
location.href = link;
}
+460
View File
@@ -0,0 +1,460 @@
var filterValues = {};
/**
* Listen filter change.
*
* @param string field
* @param string dateSelect
* @param string $filterValue
* @access public
* @return void
*/
function filterChange(field, dateSelect, $filterValue)
{
var parse = field.split('.');
field = parse[0];
var type = '';
if(parse.length == 2) type = parse[1];
var id = type.length == 0 ? field : field + '\\[' + type + '\\]';
var value = $('#' + id).val();
if(type.length == 0)
{
filterValues[field] = value;
ajaxGetChart();
}
else
{
var check = checkDate(dateSelect, $filterValue);
if(!check) return;
if(!filterValues[field]) filterValues[field] = {begin: '', end: ''};
filterValues[field][type] = value;
var begin = filterValues[field].begin;
var end = filterValues[field].end;
if((begin.length > 0 && end.length > 0) || (begin.length == 0 && end.length == 0)) ajaxGetChart();
}
}
/**
* Ajax get pivot data.
*
* @access public
* @return bool
*/
function ajaxGetChart()
{
/* If the same value is detected for the x and y axes, throw error and clear the echart, then return.*/
/* 如果x轴和y轴重复了,那么抛出错误并返回。*/
if(!checkFormSetting()) return;
var chartParams = JSON.parse(JSON.stringify(DataStorage.pivot));
chartParams.filterValues = filterValues;
/* Redraw echart. */
/* 拿数据并重绘图表。*/
$.post(createLink('pivot', 'ajaxGetChart'), chartParams, function(resp)
{
var data = JSON.parse(resp);
echart.clear();
echart.setOption(data, true);
});
}
function getQueryFilters(pivot)
{
var filters = '';
filters = pivot.filters;
filters.forEach(function(filter, index)
{
if(filter.from == 'query')
{
var find = $('#queryFilters').find('.filter-item-' + index + ' .form-' + filter.type);
if(find.length != 0) filter.default = find.val();
}
});
return filters;
}
/**
* If the same value is detected for the x and y axias, throw error and clear the echart, then return.
*
* @access public
* @return bool ture|false
*/
function checkFormSetting()
{
var pivot = DataStorage.pivot;
var type = pivot.settings[0].type;
var result = 'success';
var errorMsg = '';
if(checkForm[type])
{
for(var key in checkForm[type])
{
var fields = checkForm[type][key].split(',');
var former = fields[0];
var latter = fields[1];
if(key == 'cantequal')
{
if(pivot.settings[0][latter].includes(pivot.settings[0][former]))
{
result = 'fail';
errorMsg = pivotLang['errorList']['cantequal'];
errorMsg = errorMsg.replace(/%s/, pivotLang[type][latter]);
errorMsg = errorMsg.replace(/%s/, pivotLang[type][former]);
}
}
}
}
if(result == 'fail')
{
var message = new $.zui.Messager(errorMsg,
{
html: true,
icon: 'exclamation-sign',
type: 'danger',
close: true,
});
message.show();
echart.clear();
return false;
}
return true;
}
/**
* Validate form required.
*
* @access public
* @return void
*/
function validate(showError = false)
{
var pivot = DataStorage.pivot;
var formSettings = pivot.settings;
/* Code for temporary */
var isReady = true;
/* check group settings. */
var exist = false;
for(var key in formSettings)
{
if(key.indexOf('group') != '-1' && formSettings[key].length > 0) exist = true;
}
var tr = $('#step2Content form#groupForm table tbody tr:nth-child(1)');
tr.find('#groupLabel').remove();
tr.find('#group1').removeClass('has-error');
if(!exist)
{
isReady = false;
if(showError)
{
var error = '<div id="groupLabel" class="text-danger help-text">' + moreThanOneLang + '</div>';
tr.find('#group1').addClass('has-error');
tr.find('#group1').next().after(error);
}
}
/* check columns settings. */
formSettings.columns.forEach(function(value, index)
{
var $column = $('#step2Content form#columnForm .column-' + index);
$column.find('#column' + index + 'Label').remove();
$column.find('#stat' + index + 'Label').remove();
$column.find('#column').removeClass('has-error');
$column.find('#stat').removeClass('has-error');
if(!value.field || value.field.length == 0)
{
isReady = false;
if(showError)
{
var error = '<div id="column' + index + 'Label" class="text-danger help-text">' + notemptyLang.replace('%s', pivotLang.step2.columnField) + '</div>';
$column.find('#column').addClass('has-error');
$column.find('#column').next().after(error);
}
}
if(!value.stat || value.stat.length == 0 || value.stat === '')
{
isReady = false;
if(showError)
{
var error = '<div id="stat' + index + 'Label" class="text-danger help-text">' + notemptyLang.replace('%s', pivotLang.step2.calcMode) + '</div>';
$column.find('#stat').addClass('has-error');
$column.find('#stat').next().after(error);
}
}
});
if(isReady) $('#datagrid-tip').addClass('hidden');
return isReady;
}
/**
* Multi Validate.
*
* @param setting $setting
* @param showError $showError
* @access public
* @return void
*/
function multiValidate(setting, showError)
{
var pivot = DataStorage.pivot;
var type = pivot.settings[0].type;
var isReady = true;
var field = setting.field;
var error = '<div id="' + field + 'Label"' + ' class="text-danger help-text">' + notemptyLang.replace('%s', pivotLang[type][field]) + '</div>';
$('#pivotForm .table-form').find('.multi-' + field).each(function()
{
$(this).parent('td').find('#' + field + 'Label').remove();
$(this).parent('td').find('#' + field + '_chosen a').removeClass('has-error');
if(setting.required && $(this).val().length == 0)
{
isReady = false;
if(showError)
{
$(this).parent('td').find('#' + field + '_chosen a').addClass('has-error');
$(this).parent('td').find('#' + field + '_chosen').after(error);
}
}
});
return isReady;
}
/**
* Check date.
*
* @param string dateSelect
* @param object $filterValue
* @access public
* @return void
*/
function checkDate(dateSelect, $filterValue)
{
var begin = new Date($(dateSelect).parent().find('.default-begin').val().replace(/-/g, "\/")).getTime();
var end = new Date($(dateSelect).parent().find('.default-end').val().replace(/-/g, "\/")).getTime();
if(begin > end)
{
$(dateSelect).val('');
if(typeof $filterValue == 'object') $filterValue.val('');
bootbox.alert(pivotLang.beginGtEnd);
return false;
}
return true;
}
function waitForRepaint(callback)
{
window.requestAnimationFrame(function()
{
window.requestAnimationFrame(callback);
});
}
/**
* Init picker.
*
* @access public
* @return void
*/
function initPicker($row, pickerName = 'picker-select', onready = false)
{
$row.find('.' + pickerName).picker(
{
maxDropHeight: pickerHeight,
onReady: function()
{
if(!onready) return;
if(!$row.find('.picker')) return;
if(window.getComputedStyle($row.find('.picker').find('.picker-selections')[0]).getPropertyValue('width') !== 'auto')
{
var pickerWidth = $row.find('.picker')[0].getBoundingClientRect().width;
$row.find('.picker').find('.picker-selections').css('width', pickerWidth);
}
}
});
$row.find("." + pickerName).each(function(index)
{
if($(this).hasClass('required')) $(this).siblings("div .picker").addClass('required');
});
}
/**
* Init datapicker.
*
* @param object $obj
* @param function callback
* @access public
* @return void
*/
function initDatepicker($obj, callback)
{
$obj.find('.form-date').datepicker();
$obj.find('.form-datetime').datetimepicker();
if(typeof callback == 'function') callback($obj);
}
/**
* Attr date check.
*
* @param object $obj
* @access public
* @return void
*/
function attrDateCheck($obj)
{
$obj.find('.form-date').attr('onchange', 'checkDate(this, this.value)');
$obj.find('.form-datetime').attr('onchange', 'checkDate(this, this.value)');
}
/**
* Export file.
*
* @param object $domObj
* @access public
* @return void
*/
function exportFile($domObj)
{
if(typeof $domObj == 'undefined') return;
var fileName = $('#fileName').val().trim() ? $('#fileName').val().trim() : untitled;
var fileType = $('#fileType').val();
var tableName = fileName + '.' + fileType;
if(fileType == 'xlsx' || fileType == 'xls')
{
const new_sheet = XLSX.utils.table_to_book($domObj, {raw: true});
XLSX.writeFile(new_sheet, tableName);
}
else if(fileType == 'html' || fileType == 'mht')
{
const htmlContent = $domObj.outerHTML;
const $temp = $('<div>').html(htmlContent);
$temp.find('*').removeAttr('style');
$temp.find('*').removeAttr('class');
$temp.find('*').removeAttr('data-flex');
$temp.find('*').removeAttr('data-width');
$temp.find('*').removeAttr('data-type');
$temp.find('*').removeAttr('data-fixed-left-width');
const cleanTableHTML = $temp.html();
var head = '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
var style = '<style>table, th, td {font-size: 12px; border: 1px solid gray; border-collapse: collapse;}table th, table td {padding: 5px;}</style>';
var title = '<title>' + fileName + '</title></head>';
var body = '<body>' + cleanTableHTML + '</body>';
const finalHTML = head + style + title + body;
if(fileType == 'html')
{
const blob = new Blob([finalHTML], { type: 'text/html;charset=utf-8' });
saveAs(blob, tableName);
}
else if(fileType == 'mht')
{
const data = {html: finalHTML, fileName: fileName};
$.post(createLink('file', 'ajaxExport2mht'), data, function(resp)
{
const blob = new Blob([resp], { type: "application/x-mimearchive" });
saveAs(blob, tableName);
});
}
}
$('#export').modal('hide');
}
/**
* Zui messager alert.
*
* @param string result success|fail
* @param string mes
* @access public
* @return void
*/
function zuiMessage(result, mes)
{
var icon = result == 'success' ? 'check-circle' : 'exclamation-sign';
var type = result == 'success' ? 'success' : 'danger';
var message = new $.zui.Messager(mes,
{
html: true,
icon: icon,
type: type,
close: true,
});
message.show();
}
function select(name, options, selected, attrib, callback)
{
var type = 'option';
if(!Array.isArray(options))
{
type = options;
options = [];
}
$.post(createLink('pivot', 'ajaxGetSelect'),
{
name: name,
type: type,
selectedItems: selected,
attrib: attrib,
options: options
}, function(resp)
{
if(typeof callback == 'function') callback(resp);
});
}
function setDateField(query)
{
var $period = $('#selectPeriod');
if(!$period.length)
{
$period = $("<ul id='selectPeriod' class='dropdown-menu'><li><a href='#MONDAY'>" + datepickerText.TEXT_WEEK_MONDAY + "</a></li><li><a href='#SUNDAY'>" + datepickerText.TEXT_WEEK_SUNDAY + "</a></li><li><a href='#MONTHBEGIN'>" + datepickerText.TEXT_MONTH_BEGIN + "</a></li><li><a href='#MONTHEND'>" + datepickerText.TEXT_MONTH_END + "</a></li></ul>").appendTo('body');
$period.find('li > a').click(function(event)
{
var target = $(query).parents('table, #queryFilters, #filterItems,#filterForm').find('[data-index="' + $period.attr('data-index') + '"]').find('#default:visible');
if(target.length)
{
target.val($(this).attr('href').replace('#', '$'));
$period.hide();
}
event.stopPropagation();
return false;
});
}
if(query == '.form-date') $(query).datepicker();
if(query == '.form-datetime') $(query).datetimepicker();
$(query).on('show', function(e)
{
var $e = $(e.target);
var ePos = $e.offset();
$period.css({'left': ePos.left + 210, 'top': ePos.top + 29, 'min-height': $('.datetimepicker').outerHeight(), 'z-index': 1110}).show().attr('data-index', $e.parents('.filter-item, .filter').data('index')).find('li.active').removeClass('active');
$period.find("li > a[href='" + $e.val().replace('$', '#') + "']").closest('li').addClass('active');
}).on('changeDate', function()
{
$period.hide();
}).on('hide', function(){setTimeout(function(){$period.hide();}, 200);});
}
+298
View File
@@ -0,0 +1,298 @@
$(function()
{
if(typeof pivotID == 'undefined' || !pivotID) return;
expandTree();
renderFilters(pivot);
initQueryBtn();
$('body').resize(() => {calcPreviewGrowFilter();});
$('[data-toggle="tooltip"]').tooltip();
});
function expandTree()
{
$('.pivot-' + groupID + '-' + pivotID).addClass('active');
var $tree = $('#pivotGroups').tree({name:'tree-group'});
var tree = $tree.data('zui.tree');
tree.expand($('.pivot-' + pivotID).parents('li'));
}
/*$('.btn-export').click(function()
{
if(typeof pivotID == 'undefined' || !pivotID) return;
pivot = getQueryInfo();
});
*/
function getQueryInfo()
{
var pivotInfo = pivot;
pivotInfo.searchFilters = JSON.parse(JSON.stringify(pivotInfo.filters));
if(isQueryFilter(pivotInfo.filters))
{
pivotInfo.filters.forEach(function(filter, index)
{
var find = $('#filterItems .filter-items').find('.filter-item-' + index + ' .form-' + filter.type);
if(find.length != 0) pivotInfo.searchFilters[index].default = find.val();
});
}
else
{
pivotInfo.filters.forEach(function(filter, index)
{
var filterItem = $('#filterItems .filter-items').find('.filter-item-' + index);
var type = filter.type;
if(type == 'input')
{
var find = filterItem.find(' .form-' + type);
if(find.length != 0) pivotInfo.searchFilters[index].default = find.val();
}
else if(type == 'select')
{
var find = filterItem.find(' .form-' + type);
if(find.length != 0) pivotInfo.searchFilters[index].default = find.data('zui.picker').getValue();
}
else if(type == 'date' || type == 'datetime')
{
var begin = filterItem.find('.form-' + type + '.begin');
var end = filterItem.find('.form-' + type + '.end');
pivotInfo.searchFilters[index].default =
{
"begin": begin.length != 0 ? begin.val() : filter.default.begin,
"end": end.length != 0 ? end.val() : filter.default.end
};
}
});
}
pivotInfo.step = 4;
return pivotInfo;
}
/**
* Init query button.
*
* @access public
* @return void
*/
function initQueryBtn()
{
$('.btn-query').click(function()
{
pivotInfo = getQueryInfo();
$.post(createLink('pivot', 'ajaxGetPivot'), pivotInfo,function(resp)
{
var myDatagrid = $('#datagirdInfo');
myDatagrid.find('.reportData').remove();
myDatagrid.append(resp);
});
});
}
function calcPreviewGrowFilter()
{
if(pivot.filters.length <= 0) return;
var $filterItems = $('#filterItems .filter-items');
/* When refreshing this page, ZenTao load this page twice, when the first load isn't complete, jump back to index and load the second time,
the first load can't calc filter width, can't get the element using jQuery at first load. */
var hasInit = true;
pivot.filters.forEach(function(filter, index)
{
var nowItem = '.filter-item-' + index;
var $titleSpan = $filterItems.find(nowItem).find('.input-group-addon').first();
if(!$titleSpan.length) hasInit = false;
});
if(!hasInit) return;
var domWidth = $filterItems[0].getBoundingClientRect().width;
var nowWidth = domWidth;
var lineWrap = false;
var nowCount = 0;
var canGrowTotal = 0;
$('.query-inside').addClass('hidden');
$('.query-outside').addClass('visibility-hidden');
pivot.filters.forEach(function(filter, index)
{
var nowItem = '.filter-item-' + index;
var $nowDom = $filterItems.find(nowItem);
var leftPadding = parseInt($nowDom.css('padding-left'));
var rightPadding = parseInt($nowDom.css('padding-right'));
var spanWidth = $nowDom.find('.input-group-addon').first()[0].getBoundingClientRect().width;
var filterWidth = ((filter.type == 'input' || filter.type == 'select') ? WIDTH_INPUT : WIDTH_DATE) + (spanWidth + leftPadding + rightPadding);
/* Clear the flex-basis and set flex-basic again. */
$nowDom.css('flex-basis', '');
$nowDom.css('flex-basis', filterWidth);
if(nowWidth - filterWidth >= 0)
{
nowWidth -= filterWidth;
nowCount ++;
}
else
{
canGrowTotal += nowCount;
nowWidth = domWidth - filterWidth;
nowCount = 1;
lineWrap = true;
}
});
/* Clear all filter filter-item-grow and add class to support grow element. */
$filterItems.children().removeClass('filter-item-grow');
pivot.filters.forEach(function(filter, index)
{
var $nowDom = $filterItems.find('.filter-item-' + index);
if(canGrowTotal >= index + 1) $nowDom.addClass('filter-item-grow');
if(filter.type == 'select' && $nowDom.find('.picker').length) $nowDom.find('.picker').find('.picker-selections').css('width', WIDTH_INPUT);
});
if(!lineWrap && nowWidth >= 60) $('.query-inside').removeClass('hidden');
else $('.query-outside').removeClass('visibility-hidden');
/* Set picker-selection width, default 128px. */
waitForRepaint(function()
{
pivot.filters.forEach(function(filter, index)
{
var $nowDom = $filterItems.find('.filter-item-' + index);
if(filter.type == 'select' && $nowDom.find('.picker').length)
{
var pickerWidth = $nowDom.hasClass('filter-item-grow') ? $nowDom.find('.picker')[0].getBoundingClientRect().width : WIDTH_INPUT;
$nowDom.find('.picker').find('.picker-selections').css('width', pickerWidth);
}
});
});
}
function renderFilters(pivot)
{
if(pivot.filters.length == 0) return;
renderFilterItem(pivot.filters);
calcPreviewGrowFilter();
}
function renderFilterItem(filters)
{
$('#filterItems .filter-items').empty();
var tpl = isQueryFilter(filters) ? $('#queryFilterItemTpl').html() : $('#resultFilterItemTpl').html();
filters.forEach(function(filter, index)
{
var data =
{
index: index,
name: filter.name,
defaultValue: filter.default
};
var html = $($.zui.formatString(tpl, data))
$('#filterItems .filter-items').append(html);
isQueryFilter(filters) ? initQueryControl(html, filter) : initResultControl(html, filter);
});
$('#filterItems .filter-items').append(queryDom);
}
function initQueryControl(container, filter, object, field)
{
var type = filter.type;
var options = filter.typeOption;
var value = filter.default;
container.find('.default-block').addClass('hidden');
container.find('.default-block input[name="default"]').val('');
var control = container.find('.form-' + type);
control.val(filter.default);
control.parent('.default-block').removeClass('hidden');
if(type == 'date') setDateField('.form-date');
if(type == 'datetime') setDateField('.form-datetime');
if(type == 'select')
{
var picker = control.data('zui.picker');
if(picker) picker.destroy();
$.post(createLink('pivot', 'ajaxGetSysOptions', 'type=' + options + '&object=' + object + '&field=' + field), function(resp)
{
control.html($(resp).html());
control.picker();
control.data('zui.picker').setValue(value);
});
}
}
function initResultControl(container, filter, object, field)
{
var type = filter.type;
var value = filter.default;
container.find('.default-block').addClass('hidden');
container.find('.default-block input[name^="default"]').val('');
var control = container.find('.form-' + type);
if(type == 'date' || type == 'datetime')
{
container.find('.form-' + type + '.begin').val(filter.default.begin);
container.find('.form-' + type + '.end').val(filter.default.end);
}
else
{
control.val(filter.default);
}
control.parents('.default-block').removeClass('hidden');
if(type == 'date') control.datepicker();
if(type == 'datetime') control.datetimepicker();
if(type == 'select')
{
var picker = control.data('zui.picker');
if(picker) picker.destroy();
var fieldSetting = pivot.fieldSettings[filter.field];
var options = fieldSetting.type;
var object = fieldSetting.object;
var field = fieldSetting.field;
var pickerOptions =
{
multi: true,
maxDropHeight: pickerHeight,
onReady: function()
{
if(!control.parent().find('.picker')) return;
if(window.getComputedStyle(control.parent().find('.picker').find('.picker-selections')[0]).getPropertyValue('width') !== 'auto')
{
var pickerWidth = control.parent().find('.picker')[0].getBoundingClientRect().width;
control.parent().find('.picker').find('.picker-selections').css('width', pickerWidth);
}
}
};
if(value !== '') pickerOptions.defaultValue = value;
var pivotParams = {sql: pivot.sql, filters: getQueryFilters(pivot)};
$.post(createLink('pivot', 'ajaxGetSysOptions', 'type=' + options + '&object=' + object + '&field=' + field), pivotParams, function(resp)
{
control.html($(resp).html());
control.picker(pickerOptions);
});
}
}
function exportData()
{
const $domObj = $(".table-condensed")[0];
exportFile($domObj);
}
function isQueryFilter(filters)
{
return filters.length > 0 && filters[0].from == 'query';
}
+1 -1
View File
@@ -8,6 +8,6 @@ $('#conditions input:checkbox').change(function()
conditions = conditions.substring(0, conditions.length - 1);
var params = window.btoa('conditions=' + conditions);
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + group + '&module=pivot&method=productSummary&params=' + params);
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + groupID + '&module=pivot&method=productSummary&params=' + params);
location.href = link;
})
+1 -1
View File
@@ -31,6 +31,6 @@ function changeDate(begin, end)
}
var params = window.btoa('begin=' + begin + '&end=' + end);
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + group + '&module=pivot&method=projectdeviation&params=' + params);
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + groupID + '&module=pivot&method=projectdeviation&params=' + params);
location.href = link;
}
+1 -1
View File
@@ -23,7 +23,7 @@ function changeParams(obj)
}
var params = window.btoa('begin=' + begin + '&end=' + end + '&days=' + days + '&workday=' + workday + '&dept=' + dept + '&assign=' + assign);
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + group + '&module=pivot&method=workload&params=' + params);
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + groupID + '&module=pivot&method=workload&params=' + params);
location.href = link;
}
+1 -4
View File
@@ -146,10 +146,7 @@ $lang->pivot->deviationDesc = 'According to the Closed Execution Deviation Rate
$lang->pivot->workloadDesc = 'Workload = the total left hours of all tasks of the user / selected days * hours per day. For example: the begin and end date is January 1st to January 7th, and the total work days is 5 days, 8 hours per day. The Work load is all unfinished tasks assigned to this user to be finished in 5 days, 8 hours per day.';
$lang->pivot->featureBar = array();
$lang->pivot->featureBar['preview']['product'] = $lang->product->common;
$lang->pivot->featureBar['preview']['project'] = $lang->project->common;
$lang->pivot->featureBar['preview']['test'] = $lang->qa->common;
$lang->pivot->featureBar['preview']['staff'] = $lang->system->common;
$lang->pivot->featureBar['preview'] = array();
$lang->pivot->showProduct = 'All' . $lang->productCommon . 'Statistics';
$lang->pivot->showProject = 'All' . $lang->projectCommon . 'Statistics';
+1 -4
View File
@@ -156,10 +156,7 @@ $lang->pivot->deviationDesc = 'According to the Closed Execution Deviation Rate
$lang->pivot->workloadDesc = 'Workload = the total left hours of all tasks of the user / selected days * hours per day. For example: the begin and end date is January 1st to January 7th, and the total work days is 5 days, 8 hours per day. The Work load is all unfinished tasks assigned to this user to be finished in 5 days, 8 hours per day.';
$lang->pivot->featureBar = array();
$lang->pivot->featureBar['preview']['product'] = $lang->product->common;
$lang->pivot->featureBar['preview']['project'] = $lang->project->common;
$lang->pivot->featureBar['preview']['test'] = $lang->qa->common;
$lang->pivot->featureBar['preview']['staff'] = $lang->system->common;
$lang->pivot->featureBar['preview'] = array();
$lang->pivot->showProduct = 'All' . $lang->productCommon . 'Statistics';
$lang->pivot->showProject = 'All' . $lang->projectCommon . 'Statistics';
+1 -4
View File
@@ -146,10 +146,7 @@ $lang->pivot->deviationDesc = 'According to the Closed Execution Deviation Rate
$lang->pivot->workloadDesc = 'Workload = the total left hours of all tasks of the user / selected days * hours per day. For example: the begin and end date is January 1st to January 7th, and the total work days is 5 days, 8 hours per day. The Work load is all unfinished tasks assigned to this user to be finished in 5 days, 8 hours per day.';
$lang->pivot->featureBar = array();
$lang->pivot->featureBar['preview']['product'] = $lang->product->common;
$lang->pivot->featureBar['preview']['project'] = $lang->project->common;
$lang->pivot->featureBar['preview']['test'] = $lang->qa->common;
$lang->pivot->featureBar['preview']['staff'] = $lang->system->common;
$lang->pivot->featureBar['preview'] = array();
$lang->pivot->showProduct = 'All' . $lang->productCommon . 'Statistics';
$lang->pivot->showProject = 'All' . $lang->projectCommon . 'Statistics';
+1 -4
View File
@@ -146,10 +146,7 @@ $lang->pivot->deviationDesc = 'According to the Closed Execution Deviation Rate
$lang->pivot->workloadDesc = 'Workload = the total left hours of all tasks of the user / selected days * hours per day. For example: the begin and end date is January 1st to January 7th, and the total work days is 5 days, 8 hours per day. The Work load is all unfinished tasks assigned to this user to be finished in 5 days, 8 hours per day.';
$lang->pivot->featureBar = array();
$lang->pivot->featureBar['preview']['product'] = $lang->product->common;
$lang->pivot->featureBar['preview']['project'] = $lang->project->common;
$lang->pivot->featureBar['preview']['test'] = $lang->qa->common;
$lang->pivot->featureBar['preview']['staff'] = $lang->system->common;
$lang->pivot->featureBar['preview'] = array();
$lang->pivot->showProduct = 'All' . $lang->productCommon . 'Statistics';
$lang->pivot->showProject = 'All' . $lang->projectCommon . 'Statistics';
+1 -4
View File
@@ -156,10 +156,7 @@ $lang->pivot->deviationDesc = '按照已关闭执行统计偏差率(偏差率
$lang->pivot->workloadDesc = '工作负载=用户所有任务剩余工时之和/选择的时间天数*每天的工时。例如:起止时间设为1月1日~1月7日、工作日天数5天、每天工时8h,统计的是所有指派给该人员的未完成的任务,在5天内,每天8h的情况下的工作负载。';
$lang->pivot->featureBar = array();
$lang->pivot->featureBar['preview']['product'] = $lang->product->common;
$lang->pivot->featureBar['preview']['project'] = $lang->project->common;
$lang->pivot->featureBar['preview']['test'] = $lang->qa->common;
$lang->pivot->featureBar['preview']['staff'] = $lang->system->common;
$lang->pivot->featureBar['preview'] = array();
$lang->pivot->showProduct = '所有' . $lang->productCommon . '统计数据';
$lang->pivot->showProject = '所有' . $lang->projectCommon . '统计数据';
+1 -4
View File
@@ -104,7 +104,4 @@ $lang->pivot->deviationDesc = '按照已關閉執行統計偏差率(偏差率
$lang->pivot->workloadDesc = '工作負載=用戶所有任務剩餘工時之和/選擇的時間天數*每天的工時。例如:起止時間設為1月1日~1月7日、工作日天數5天、每天工時8h,統計的是所有指派給該人員的未完成的任務,在5天內,每天8h的情況下的工作負載。';
$lang->pivot->featureBar = array();
$lang->pivot->featureBar['preview']['product'] = $lang->product->common;
$lang->pivot->featureBar['preview']['project'] = $lang->project->common;
$lang->pivot->featureBar['preview']['test'] = $lang->qa->common;
$lang->pivot->featureBar['preview']['staff'] = $lang->system->common;
$lang->pivot->featureBar['preview'] = array();
+70 -57
View File
@@ -62,8 +62,6 @@ class pivotModel extends model
public function getList($dimensionID = 0, $groupID = 0, $orderBy = 'id_desc', $pager = null)
{
$this->loadModel('screen');
$pivots = array();
if($groupID)
{
$groups = $this->dao->select('id')->from(TABLE_MODULE)
@@ -79,40 +77,54 @@ class pivotModel extends model
}
$conditions = trim($conditions, 'or');
$pivots += $this->dao->select('*')->from(TABLE_PIVOT)
$pivots = $this->dao->select('*')->from(TABLE_PIVOT)
->where('deleted')->eq(0)
->beginIF($conditions)->andWhere("({$conditions})")->fi()
->beginIF(!empty($dimensionID))->andWhere('dimension')->eq($dimensionID)->fi()
->orderBy($orderBy)
->fetchAll();
$pivots += $this->dao->select('*')->from(TABLE_CHART)
$charts = $this->dao->select('*')->from(TABLE_CHART)
->where('deleted')->eq(0)
->andWhere('type')->eq('table')
->beginIF($conditions)->andWhere("({$conditions})")->fi()
->beginIF(!empty($dimensionID))->andWhere('dimension')->eq($dimensionID)->fi()
->orderBy($orderBy)
->fetchAll();
$pivots = array_merge($pivots, $charts);
}
else
{
$pivots += $this->dao->select('*')->from(TABLE_PIVOT)
$pivots = $this->dao->select('*')->from(TABLE_PIVOT)
->where('deleted')->eq(0)
->beginIF(!empty($dimensionID))->andWhere('dimension')->eq($dimensionID)->fi()
->orderBy($orderBy)
->fetchAll();
$pivots += $this->dao->select('*')->from(TABLE_CHART)
$charts = $this->dao->select('*')->from(TABLE_CHART)
->where('deleted')->eq(0)
->andWhere('type')->eq('table')
->beginIF(!empty($dimensionID))->andWhere('dimension')->eq($dimensionID)->fi()
->orderBy($orderBy)
->fetchAll();
$pivots = array_merge($pivots, $charts);
}
$pager->setRecTotal(count($pivots));
$pager->setPageTotal();
if($pager->pageID > $pager->pageTotal) $pager->setPageID($pager->pageTotal);
if(!empty($pager))
{
$pager->setRecTotal(count($pivots));
$pager->setPageTotal();
if($pager->pageID > $pager->pageTotal) $pager->setPageID($pager->pageTotal);
if($pivots)
{
$pivots = array_chunk($pivots, $pager->recPerPage);
$pivots = $pivots[$pager->pageID - 1];
}
}
return $this->processPivot($pivots, false);
}
@@ -127,7 +139,7 @@ class pivotModel extends model
*/
public function processDateVar($var, $type = 'date')
{
if(empty($var)) return $var;
if(empty($var)) return NULL;
$format = $type == 'datetime' ? 'Y-m-d H:i:s' : 'Y-m-d';
switch($var)
@@ -1388,19 +1400,16 @@ class pivotModel extends model
/* Process rows. */
$connectSQL = '';
if(empty($settings['filterType']) or $settings['filterType'] == 'result')
if(!empty($filters) && !isset($filters[0]['from']))
{
if(!empty($filters))
$wheres = array();
foreach($filters as $field => $filter)
{
$wheres = array();
foreach($filters as $field => $filter)
{
$wheres[] = "tt.`$field` {$filter['operator']} {$filter['value']}";
}
$whereStr = implode(' and ', $wheres);
$connectSQL .= " where $whereStr";
$wheres[] = "tt.`$field` {$filter['operator']} {$filter['value']}";
}
$whereStr = implode(' and ', $wheres);
$connectSQL .= " where $whereStr";
}
$groupSQL = " group by $groupList";
@@ -1409,36 +1418,39 @@ class pivotModel extends model
$number = 0;
$groupsRow = array();
$showColTotal = zget($settings, 'columnTotal', 'noShow');
foreach($settings['columns'] as $column)
if(isset($settings['columns']))
{
$stat = $column['stat'];
$field = $column['field'];
$slice = zget($column, 'slice', 'noSlice');
$uuName = $field . $number;
$number ++;
if($stat == 'distinct')
foreach($settings['columns'] as $column)
{
$columnSQL = "count(distinct tt.`$field`) as `$uuName`";
}
else
{
$columnSQL = "$stat(tt.`$field`) as `$uuName`";
}
$stat = $column['stat'];
$field = $column['field'];
$slice = zget($column, 'slice', 'noSlice');
$uuName = $field . $number;
$number ++;
if($slice != 'noSlice') $columnSQL = "select $groupList,`$slice`,$columnSQL from ($sql) tt" . $connectSQL . $groupSQL . ",tt.`$slice`" . $orderSQL . ",tt.`$slice`";
if($slice == 'noSlice') $columnSQL = "select $groupList,$columnSQL from ($sql) tt" . $connectSQL . $groupSQL . $orderSQL;
if($stat == 'distinct')
{
$columnSQL = "count(distinct tt.`$field`) as `$uuName`";
}
else
{
$columnSQL = "$stat(tt.`$field`) as `$uuName`";
}
$columnRows = $this->dao->query($columnSQL)->fetchAll();
if($slice != 'noSlice') $columnSQL = "select $groupList,`$slice`,$columnSQL from ($sql) tt" . $connectSQL . $groupSQL . ",tt.`$slice`" . $orderSQL . ",tt.`$slice`";
if($slice == 'noSlice') $columnSQL = "select $groupList,$columnSQL from ($sql) tt" . $connectSQL . $groupSQL . $orderSQL;
$cols = $this->getTableHeader($columnRows, $column, $fields, $cols, $sql, $langs);
if($slice != 'noSlice') $columnRows = $this->processSliceData($columnRows, $groups, $slice, $uuName);
$columnRows = $this->processShowData($columnRows, $groups, $column, $showColTotal, $uuName);
$columnRows = $this->dao->query($columnSQL)->fetchAll();
foreach($columnRows as $key => $row)
{
if(!isset($groupsRow[$key])) $groupsRow[$key] = new stdclass();
$groupsRow[$key] = (object)array_merge((array)$groupsRow[$key], (array)$row);
$cols = $this->getTableHeader($columnRows, $column, $fields, $cols, $sql, $langs);
if($slice != 'noSlice') $columnRows = $this->processSliceData($columnRows, $groups, $slice, $uuName);
$columnRows = $this->processShowData($columnRows, $groups, $column, $showColTotal, $uuName);
foreach($columnRows as $key => $row)
{
if(!isset($groupsRow[$key])) $groupsRow[$key] = new stdclass();
$groupsRow[$key] = (object)array_merge((array)$groupsRow[$key], (array)$row);
}
}
}
@@ -1461,12 +1473,7 @@ class pivotModel extends model
$options = $this->getSysOptions($fields[$group]['type'], $fields[$group]['object'], $fields[$group]['field'], $sql);
foreach($groupsRow as $row)
{
if(isset($row->$group))
{
$value = $row->$group;
$lang = isset($options[$value]) ? $options[$value] : $value;
$row->$group = $lang;
}
if(isset($row->$group)) $row->$group = zget($options, $row->$group);
}
}
@@ -1771,7 +1778,7 @@ class pivotModel extends model
{
if(in_array($field, $groups))
{
$colTotalRow->$field = 0;
$colTotalRow->$field = '$togalGroup$';
}
else
{
@@ -1904,20 +1911,26 @@ class pivotModel extends model
case 'dept':
$options = $this->loadModel('dept')->getOptionMenu(0);
break;
case 'project.status':
$this->app->loadLang('project');
$options = $this->lang->project->statusList;
break;
case 'option':
if($field)
{
$path = $this->app->getExtensionRoot() . 'biz' . DS . 'dataview' . DS . 'table' . DS . "$object.php";
include $path;
$options = $schema->fields[$field]['options'];
$path = $this->app->getModuleRoot() . 'dataview' . DS . 'table' . DS . "$object.php";
if(is_file($path))
{
include $path;
$options = $schema->fields[$field]['options'];
}
}
break;
case 'object':
if($field)
{
$table = zget($this->config->objectTables, $object);
$options = $this->dao->select("id, {$field}")->from($table)->fetchPairs();
$table = zget($this->config->objectTables, $object, '');
if($table) $options = $this->dao->select("id, {$field}")->from($table)->fetchPairs();
}
break;
case 'string':
+8 -17
View File
@@ -1,39 +1,30 @@
<?php include '../../common/view/header.html.php';?>
<script>
$('#subNavbar li').not('[data-id=<?php echo $group;?>]').removeClass('active');
$('#subNavbar li').not('[data-id=<?php echo $groupID;?>]').removeClass('active');
</script>
<?php if($this->config->edition != 'open'):?>
<style>#mainContent > .side-col.col-lg{width: 210px}</style>
<style>.hide-sidebar #sidebar{width: 0 !important}</style>
<?php endif;?>
<?php js::set('dimension', $dimension);?>
<?php js::set('group', $group);?>
<?php js::set('groupID', $groupID);?>
<?php if($this->config->edition == 'open'):?>
<div id="mainMenu" class='clearfix'>
<div class="btn-toolbar pull-left">
<?php foreach($lang->pivot->featureBar['preview'] as $key => $label):?>
<?php $active = ($key == $group) ? ' btn-active-text' : '';?>
<?php echo html::a(inlink('preview', "dimension=$dimension&group=$key"), "<span class='text'>$label</span>", '', "class='btn btn-link {$active}'");?>
<?php endforeach;?>
</div>
</div>
<?php endif;?>
<?php if($this->config->edition == 'biz' or $this->config->edition == 'max'):?>
<div id='mainMenu' class='clearfix main-position'>
<div class="btn-toolbar pull-left parent-position">
<?php foreach($lang->pivot->featureBar['preview'] as $key => $label):?>
<?php $active = ($key == $group) ? ' btn-active-text' : '';?>
<?php $active = ($key == $groupID) ? ' btn-active-text' : '';?>
<?php echo html::a(inlink('preview', "dimension=$dimension&group=$key"), "<span class='text'>$label</span>", '', "class='btn btn-link {$active}'");?>
<?php endforeach;?>
</div>
<?php if($this->config->edition == 'biz' or $this->config->edition == 'max'):?>
<div class='btn-toolbar pull-right child-position'>
<?php if(common::hasPriv('pivot', 'export')):?>
<a href="#" class="btn btn-link btn-export hidden" data-toggle="modal" data-target="#export"><?php echo '<i class="icon-export muted"> </i>' . $lang->export;?></a>
<?php endif;?>
<?php common::printLink('pivot', 'browse', '', $lang->pivot->toDesign, '', "class='btn btn-primary'");?>
</div>
<?php endif;?>
</div>
<?php if($this->config->edition == 'biz' or $this->config->edition == 'max'):?>
<?php $pivotPath = $this->app->getModuleExtPath('', 'pivot', 'view');?>
<?php include $pivotPath['common'] . 'exportdata.html.php';?>
<?php endif;?>
@@ -45,8 +36,8 @@ $('#subNavbar li').not('[data-id=<?php echo $group;?>]').removeClass('active');
</div>
<div class="cell">
<div class='panel'>
<div class='panel-heading'>
<div class='panel-title'><?php echo $lang->pivot->list;?></div>
<div class='panel-heading text-ellipsis'>
<div class='panel-title'><?php echo isset($group->name) ? $group->name : '';?></div>
</div>
<div class='panel-body'>
<div class='list-group'>
+1 -1
View File
@@ -46,7 +46,7 @@
<?php endif;?>
</div>
<div id='datagirdInfo' class='datagrid datagrid-padding'>
<?php $sql = $this->loadModel('dataview')->parseSqlVars($pivot->sql, $pivot->filters);?>
<?php $sql = $this->loadModel('chart')->parseSqlVars($pivot->sql, $pivot->filters);?>
<?php $this->pivot->buildPivotTable($data, $configs, json_decode(json_encode($pivot->fieldSettings), true), $sql);?>
</div>
</div>
-1
View File
@@ -1,7 +1,6 @@
<style>
<?php helper::import('../css/workload.css');?>
<?php if($this->config->edition != 'open'):?>
#mainContent > .side-col.col-lg{width: 210px}
.hide-sidebar #sidebar{width: 0 !important}
<?php endif;?>
</style>
+184 -32
View File
@@ -5,25 +5,28 @@ class pivotZen extends pivot
* Prepare for preview a pivot.
*
* @param int $dimension
* @param string $group
* @param string $groupID
* @param string $module
* @param string $method
* @param string $params
* @access public
* @return void
*/
public function prepare4Preview($dimension, $group, $module, $method, $params)
public function prepare4Preview($dimension, $groupID, $module, $method, $params)
{
$params = helper::safe64Decode($params);
if(!$group) $group = $this->getDefaultGroup($dimension);
if(!$module || !$method) list($module, $method, $params) = $this->getDefaultMethod($dimension, $group);
if(!$groupID) $groupID = $this->getDefaultGroup($dimension);
if(!$module || !$method) list($module, $method, $params) = $this->getDefaultPivotParams($dimension, $groupID);
if(!empty($module) && !empty($method) && $method != 'show' && !common::hasPriv($module, $method)) $this->loadModel('common')->deny('pivot', $method);
$this->view->sidebar = $this->getSidebar($dimension, $group, $module, $method, $params);
$this->setFeatureBar($dimension);
$this->view->sidebar = $this->getSidebar($dimension, $groupID, $module, $method, $params);
$this->view->dimension = $dimension;
$this->view->group = $group;
$this->view->groupID = $groupID;
$this->view->group = $this->loadModel('tree')->getByID($groupID);
$this->view->module = $module;
$this->view->method = $method;
$this->view->params = $params;
@@ -40,37 +43,74 @@ class pivotZen extends pivot
*/
public function getDefaultGroup($dimension)
{
foreach($this->lang->pivotList as $group => $list)
{
if(empty($list->lists)) continue;
$group = $this->getFirstGroup($dimension);
if(!$group) return 0;
foreach($list->lists as $item)
{
$items = explode('|', $item);
if(count($items) < 3) continue;
list($label, $module, $method) = $items;
if(common::hasPriv($module, $method)) return $group;
}
}
return '';
return $group->id;
}
/**
* Get default module name and method name and params of pivot in a group.
* Get first group of a dimension.
*
* @param int $dimension
* @param string $group
* @access public
* @return int
*/
public function getFirstGroup($dimension)
{
if(empty($dimension)) return 0;
return $this->dao->select('*')->from(TABLE_MODULE)
->where('deleted')->eq('0')
->andWhere('type')->eq('pivot')
->andWhere('root')->eq($dimension)
->orderBy('grade, `order`')
->limit(1)
->fetch();
}
/**
* Get default module name and method name of a pivot in a group.
*
* @param int $dimension
* @param int $group
* @access public
* @return array
*/
public function getDefaultMethod($dimension, $group)
public function getDefaultPivotParams($dimension, $group)
{
if(empty($this->lang->pivotList->$group->lists)) return array('', '', '');
$currentGroup = $this->loadModel('tree')->getByID($group);
if(empty($currentGroup) || $currentGroup->grade != 1) return array('', '', '');
foreach($this->lang->pivotList->$group->lists as $item)
$groups = $this->dao->select('id, grade, name, collector')->from(TABLE_MODULE)
->where('deleted')->eq('0')
->andWhere('root')->eq($dimension)
->andWhere('path')->like("$currentGroup->path%")
->orderBy('`order`')
->fetchAll();
if(!$groups) return array('', '', '');
foreach($groups as $group)
{
if($this->config->edition == 'open' && $group->grade == 1) continue;
$pivots = $this->dao->select('*')->from(TABLE_PIVOT)
->where("FIND_IN_SET($group->id, `group`)")
->andWhere('stage')->ne('draft')
->orderBy('id_desc')
->fetchAll();
if($pivots)
{
foreach($pivots as $pivot) return array('pivot', 'show', "dimensionID=$dimension&groupID={$group->id}&pivotID={$pivot->id}");
}
}
if(empty($this->lang->pivotList->{$currentGroup->collector}->lists)) return array('', '', '');
$firstDimension = $this->loadModel('dimension')->getFirst();
if($dimension != $firstDimension->id) return array('', '', '');
foreach($this->lang->pivotList->{$currentGroup->collector}->lists as $item)
{
$items = explode('|', $item . '|');
if(count($items) < 4) continue;
@@ -83,11 +123,33 @@ class pivotZen extends pivot
return array('', '', '');
}
/**
* Set pivot Menu of a dimension.
*
* @param int $dimension
* @access public
* @return void
*/
public function setFeatureBar($dimension)
{
if(!$dimension) return false;
$groups = $this->loadModel('tree')->getGroupPairs($dimension, 0, 1, 'pivot');
if(!$groups) return false;
$this->lang->pivot->featureBar['preview'] = array();
foreach($groups as $groupID => $groupName)
{
if(empty($groupID) || empty($groupName)) continue;
$this->lang->pivot->featureBar['preview'][$groupID] = $groupName;
}
}
/**
* Get sidebar of pivot.
*
* @param int $dimension
* @param string $group
* @param int $group
* @param string $module
* @param string $method
* @param string $params
@@ -96,14 +158,104 @@ class pivotZen extends pivot
*/
public function getSidebar($dimension, $group, $module, $method, $params)
{
if(empty($this->lang->pivotList->$group->lists)) return '';
if(!$group) return '';
$currentGroup = $this->loadModel('tree')->getByID($group);
if(empty($currentGroup) || $currentGroup->grade != 1) return '';
$groups = $this->dao->select('id, grade, name, collector')->from(TABLE_MODULE)
->where('deleted')->eq('0')
->andWhere('root')->eq($dimension)
->andWhere('path')->like("$currentGroup->path%")
->orderBy('`order`')
->fetchAll();
if(!$groups) return '';
$pivotID = 0;
if($module == 'pivot' && $method == 'show')
{
parse_str($params, $params);
if(isset($params['pivotID'])) $pivotID = $params['pivotID'];
}
$clientLang = $this->app->getClientLang();
if(!isset($this->config->langs[$clientLang])) $clientLang = 'zh-cn';
$index = 1;
$sidebar = '';
foreach($groups as $group)
{
if($this->config->edition == 'open' && $group->grade == 1) continue;
$pivots = $this->dao->select('*')->from(TABLE_PIVOT)
->where("FIND_IN_SET($group->id, `group`)")
->andWhere('stage')->ne('draft')
->andWhere('deleted')->eq(0)
->orderBy('id_desc')
->fetchAll();
if(empty($group->collector) && empty($pivots)) continue;
if($pivots) $pivots = $this->pivot->processPivot($pivots, false);
if($group->grade == 2)
{
$class = $index == 1 ? 'open' : 'closed';
$sidebar .= "<li class='$class'><a>$group->name</a><ul>";
}
foreach($pivots as $pivot)
{
$class = "pivot-{$pivot->id}";
$pivotName = $pivot->name;
$params = helper::safe64Encode("dimensionID=$pivot->dimension&groupID=$pivot->group&pivotID=$pivot->id");
if($module == 'pivot' && $method == 'show' && $pivotID == $pivot->id)
{
$class .= ' active';
$this->view->title = $pivotName;
}
$pivotLink = helper::createLink('pivot', 'preview', "dimension=$dimension&group=$currentGroup->id&module=pivot&method=show&params=$params");
$sidebar .= "<li class='$class'>" . html::a($pivotLink, $pivotName, '', "title='$pivotName'") . '</li>';
}
if($group->grade == 2) $sidebar .= '</ul></li>';
$index++;
}
$sidebar .= $this->getBuiltinSidebar($dimension, $currentGroup, $module, $method);
if($sidebar) $sidebar = "<ul id='pivotGroups' class='tree' data-ride='tree'>" . $sidebar . '</ul>';
return $sidebar;
}
/**
* Display the built-in pivots in the first dimension.
*
* @param int $dimension
* @param object $group
* @param string $module
* @param string $method
* @access public
* @return string
*/
public function getBuiltinSidebar($dimension, $group, $module, $method)
{
$firstDimension = $this->loadModel('dimension')->getFirst();
if($dimension != $firstDimension->id) return '';
$collector = $group->collector;
if(empty($this->lang->pivotList->$collector->lists)) return '';
$sidebar = '';
$module = strtolower($module);
$method = strtolower($method);
ksort($this->lang->pivotList->$group->lists);
foreach($this->lang->pivotList->$group->lists as $item)
ksort($this->lang->pivotList->$collector->lists);
foreach($this->lang->pivotList->$collector->lists as $item)
{
$items = explode('|', $item . '|');
if(count($items) < 4) continue;
@@ -113,13 +265,13 @@ class pivotZen extends pivot
$class = '';
if($module == strtolower($moduleName) && $method == strtolower($methodName))
{
$class = 'selected';
$class = "class='active'";
$this->view->title = $label;
}
$params = helper::safe64Encode($params);
if(common::hasPriv($moduleName, $methodName)) $sidebar .= html::a(helper::createLink('pivot', 'preview', "dimension=$dimension&group=$group&module=$moduleName&method=$methodName&params=$params"), '<i class="icon icon-file-text"></i> ' . $label, '', "class='$class' title='$label'");
if(common::hasPriv($moduleName, $methodName)) $sidebar .= "<li $class>" . html::a(helper::createLink('pivot', 'preview', "dimension=$dimension&group=$group->id&module=$moduleName&method=$methodName&params=$params"), $label, '', "title='$label'") . '</li>';
}
return $sidebar;
+7 -4
View File
@@ -241,6 +241,7 @@ class productModel extends model
*/
public function getById($productID)
{
$productID = (int)$productID;
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getProduct();
$product = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch();
if(!$product) return false;
@@ -367,7 +368,7 @@ class productModel extends model
/* Order by program. */
return $this->dao->select("t1.*, IF(INSTR(' closed', t1.status) < 2, 0, 1) AS isClosed")->from(TABLE_PRODUCT)->alias('t1')
->leftJoin(TABLE_PROGRAM)->alias('t2')->on('t1.program = t2.id')
->where(1)
->where('1=1')
->beginIF(strpos($mode, 'all') === false)->andWhere('t1.deleted')->eq(0)->fi()
->beginIF($programID)->andWhere('t1.program')->eq($programID)->fi()
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('t1.status')->ne('closed')->fi()
@@ -439,6 +440,8 @@ class productModel extends model
return $this->loadModel('tutorial')->getExecutionProducts();
}
if(strpos($projectID, 'all') !== false) $projectID = str_replace('all', 0, $projectID);
if(!empty($append) and is_array($append)) $append = implode(',', $append);
$views = empty($append) ? $this->app->user->view->products : $this->app->user->view->products . ",$append";
@@ -1300,7 +1303,7 @@ class productModel extends model
->beginIF(strpos($param, 'multiple') !== false)->andWhere('t2.multiple')->ne('0')->fi()
->andWhere('t2.type')->eq('project')
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->projects)->fi()
->beginIF($product->type != 'normal' and $branch !== '')->andWhere('t1.branch')->in($branch)->fi()
->beginIF($product->type != 'normal' and $branch !== '' and $branch != 'all')->andWhere('t1.branch')->in($branch)->fi()
->andWhere('t2.deleted')->eq('0')
->beginIF($appendProject)->orWhere('t2.id')->in($appendProject)->fi()
->orderBy('order_asc')
@@ -1472,7 +1475,7 @@ class productModel extends model
->where('t1.product')->eq($productID)
->andWhere('t2.type')->in('sprint,kanban,stage')
->beginIF($projectID)->andWhere('t2.project')->in($projectID)->fi()
->beginIF($branch !== '')->andWhere('t1.branch')->in($branch)->fi()
->beginIF($branch !== '' and $branch !== 'all')->andWhere('t1.branch')->in($branch)->fi()
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->sprints)->fi()
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('t2.status')->ne('closed')->fi()
->beginIF(strpos($mode, 'multiple') !== false)->andWhere('t2.multiple')->eq('1')->fi()
@@ -1532,7 +1535,7 @@ class productModel extends model
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
->where('t1.product')->eq($productID)
->andWhere('t2.type')->in('stage,sprint,kanban')
->beginIF($branch)->andWhere('t1.branch')->in($branch)->fi()
->beginIF($branch and $branch != 'all')->andWhere('t1.branch')->in($branch)->fi()
->beginIF($projectID)->andWhere('t2.project')->eq($projectID)->fi()
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->sprints)->fi()
->andWhere('t2.deleted')->eq('0')
+1 -1
View File
@@ -596,7 +596,7 @@ class programModel extends model
}
$query = str_replace('`id`','t1.id', $this->session->projectQuery);
$projectList = $this->dao->select('t1.*')->from(TABLE_PROJECT)->alias('t1')
$projectList = $this->dao->select('DISTINCT t1.*')->from(TABLE_PROJECT)->alias('t1')
->leftJoin(TABLE_TEAM)->alias('t2')->on('t1.id=t2.root')
->leftJoin(TABLE_STAKEHOLDER)->alias('t3')->on('t1.id=t3.objectID')
->where('t1.deleted')->eq('0')
+10 -5
View File
@@ -904,7 +904,7 @@ class project extends control
/* Check exist extend fields. */
$isExtended = false;
if(!empty($this->config->bizVersion))
if($this->config->edition != 'open')
{
$extend = $this->loadModel('workflowaction')->getByModuleAndAction('project', 'view');
if(!empty($extend) and $extend->extensionType == 'extend') $isExtended = true;
@@ -2345,12 +2345,17 @@ class project extends control
*/
public function ajaxGetExecutions($projectID, $executionID = 0, $mode = '', $type = 'all')
{
$project = $this->project->getById($projectID);
$executions = array('' => '') + $this->loadModel('execution')->getPairs($projectID, $type, $mode);
$disabled = '';
$executions = array('' => '');
if($projectID)
{
$project = $this->project->getById($projectID);
$executions = array('' => '') + $this->loadModel('execution')->getPairs($projectID, $type, $mode);
$disabled = !empty($project->multiple) ? '' : 'disabled';
}
if($this->app->getViewType() == 'json') return print(json_encode($executionList));
$disabled = $project->multiple ? '' : 'disabled';
return print(html::select('execution', $executions, $executionID, "class='form-control $disabled' $disabled"));
}
+2
View File
@@ -139,6 +139,8 @@ class projectModel extends model
}
}
setcookie('lastProject', (int)$this->session->project, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
return $this->session->project;
}

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