Merge branch 'master' into 'sprint_sunjun_29766'

# Conflicts:
#   module/kanban/config.php
This commit is contained in:
李玉春
2022-05-25 02:27:08 +00:00
100 changed files with 1089 additions and 630 deletions
+166 -199
View File
@@ -90,6 +90,22 @@ DELETE FROM `zt_config` WHERE `section` = 'customMenu';
UPDATE `zt_story` SET `plan` = '' WHERE `plan` = 0;
REPLACE INTO `zt_workflowdatasource` (`type`, `name`, `code`, `buildin`, `datasource`, `view`, `keyField`, `valueField`) VALUES
('lang', '项目模型', 'projectModel', '1', 'projectModel', '', '', ''),
('lang', '反馈类型', 'feedbackType', '1', 'feedbackType', '', '', ''),
('lang', '反馈处理方案', 'feedbackSolution', '1', 'feedbackSolution', '', '', ''),
('lang', '反馈关闭原因', 'feedbackclosedReason', '1', 'feedbackclosedReason', '', '', ''),
('lang', '任务关闭原因', 'taskReason', '1', 'taskReason', '', '', ''),
('lang', '套件类型', 'testsuiteAuth', '1', 'testsuiteAuth', '', '', ''),
('system', '项目集', 'programs', '1', '{\"app\":\"system\",\"module\":\"program\",\"method\":\"getPairs\",\"methodDesc\":\"Get program pairs.\",\"params\":[{\"name\":\"isQueryAll\",\"type\":\"bool\",\"desc\":\"\",\"value\":\"\"},{\"name\":\"orderBy\",\"type\":\"string\",\"desc\":\"\",\"value\":\"id_desc\"}]}', '', '', ''),
('lang', '需求关闭原因', 'storyClosedReason', '1', 'storyClosedReason', '', '', '');
INSERT INTO `zt_workflowdatasource` (`type`, `name`, `code`, `buildin`, `vision`, `datasource`, `view`, `keyField`, `valueField`) VALUES
('lang', '反馈类型', 'litefeedbackType', '1', 'lite', 'feedbackType', '', '', ''),
('lang', '反馈处理方案', 'litefeedbackSolution', '1', 'lite', 'feedbackSolution', '', '', ''),
('lang', '反馈关闭原因', 'litefeedbackclosedReason', '1', 'lite', 'feedbackclosedReason', '', '', ''),
('lang', '任务关闭原因', 'litetaskReason', '1', 'lite', 'taskReason', '', '', '');
UPDATE `zt_workflowfield` set `type` = 'datetime', `control` = 'datetime' WHERE `module` = 'testcase' and `field` IN ('openedDate','reviewedDate','lastEditedDate','lastRunDate');
UPDATE `zt_workflowfield` set `control` = 'date' WHERE `module` = 'testtask' and `field` IN ('begin','end');
@@ -117,53 +133,69 @@ UPDATE `zt_workflowfield` SET `type` = 'datetime', `control` = 'datetime' WHERE
UPDATE `zt_workflowfield` SET `control` = 'datetime' WHERE `module` = 'story' and `field` = 'closedDate';
UPDATE `zt_workflowfield` SET `control` = 'radio' WHERE `module` = 'story' and `field` = 'deleted';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'product' and `action` = 'all' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `type` = 'batch', `position` = 'browse' WHERE `module` = 'product' and `action` = 'batchedit' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'product' and `action` = 'browse' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'product' and `action` = 'view' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `show` = 'direct' WHERE `module` = 'product' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `type` = 'batch', `position` = 'browse' WHERE `module` = 'productplan' and `action` = 'batchedit' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'productplan' and `action` = 'browse' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `show` = 'direct' WHERE `module` = 'productplan' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'productplan' and `action` = 'view' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'release' and `action` = 'browse' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `show` = 'direct' WHERE `module` = 'release' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'release' and `action` = 'view' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `type` = 'batch' WHERE `module` = 'story' and `action` = 'batchcreate' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `type` = 'batch' WHERE `module` = 'story' and `action` = 'batchedit' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'story' and `action` = 'browse' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'story' and `action` = 'exporttemplate' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'story' and `action` = 'import' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'story' and `action` = 'view' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'story' and `action` = 'batchcreate' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'story' and `action` = 'batchedit' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `show` = 'direct' WHERE `module` = 'story' and `vision` = 'rnd' and action NOT IN ('exporttemplate', 'import');
UPDATE `zt_workflowaction` SET `show` = 'direct' WHERE `module` = 'program' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'program' and `vision` = 'rnd';
DELETE FROM `zt_workflowfield` WHERE `module`='execution' AND `field`='stage';
DELETE FROM `zt_workflowfield` WHERE `module`='program' AND `field`='stage';
DELETE FROM `zt_workflowfield` WHERE `module`='project' AND `field`='stage';
DELETE FROM `zt_workflowfield` WHERE `module`='bug' AND `field`='feedback';
DELETE FROM `zt_workflowfield` WHERE `module`='task' AND `field`='feedback';
REPLACE INTO `zt_workflowdatasource` (`type`, `name`, `code`, `buildin`, `datasource`, `view`, `keyField`, `valueField`) VALUES
('lang', '项目模型', 'projectModel', '1', 'projectModel', '', '', ''),
('lang', '反馈类型', 'feedbackType', '1', 'feedbackType', '', '', ''),
('lang', '反馈处理方案', 'feedbackSolution', '1', 'feedbackSolution', '', '', ''),
('lang', '反馈关闭原因', 'feedbackclosedReason', '1', 'feedbackclosedReason', '', '', ''),
('lang', '任务关闭原因', 'taskReason', '1', 'taskReason', '', '', ''),
('lang', '需求关闭原因', 'storyClosedReason', '1', 'storyClosedReason', '', '', ''),
('lang', '套件类型', 'testsuiteAuth', '1', 'testsuiteAuth', '', '', ''),
('system', '项目集', 'programs', '1', '{\"app\":\"system\",\"module\":\"program\",\"method\":\"getPairs\",\"methodDesc\":\"Get program pairs.\",\"params\":[{\"name\":\"isQueryAll\",\"type\":\"bool\",\"desc\":\"\",\"value\":\"\"},{\"name\":\"orderBy\",\"type\":\"string\",\"desc\":\"\",\"value\":\"id_desc\"}]}', '', '', '');
INSERT INTO `zt_workflowdatasource` (`type`, `name`, `code`, `buildin`, `vision`, `datasource`, `view`, `keyField`, `valueField`) VALUES
('lang', '反馈类型', 'litefeedbackType', '1', 'lite', 'feedbackType', '', '', ''),
('lang', '反馈处理方案', 'litefeedbackSolution', '1', 'lite', 'feedbackSolution', '', '', ''),
('lang', '反馈关闭原因', 'litefeedbackclosedReason', '1', 'lite', 'feedbackclosedReason', '', '', ''),
('lang', '任务关闭原因', 'litetaskReason', '1', 'lite', 'taskReason', '', '', '');
REPLACE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `control`, `expression`, `options`, `default`, `rules`, `placeholder`, `order`, `searchOrder`, `exportOrder`, `canExport`, `canSearch`, `isValue`, `readonly`, `buildin`, `desc`, `createdBy`, `createdDate`, `editedBy`, `editedDate`) VALUES
('program', 'type', 'char', '30', '类型', 'select', '', '16', 'sprint', '', '', 2, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'begin', 'date', '', '计划开始', 'date', '', '', '', '', '', 15, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'end', 'date', '', '计划完成', 'date', '', '', '', '', '', 16, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'days', 'smallint', '5', '可用工作日', 'integer', '', '', '', '', '', 19, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'pri', 'enum', '', '优先级', 'select', '', '[1,2,3,4]', '1', '', '', 21, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'desc', 'text', '', '项目集描述', 'richtext', '', '', '', '', '', 22, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'openedDate', 'datetime', '', '创建日期', 'datetime', '', '', '', '', '', 28, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'closedDate', 'datetime', '', '关闭日期', 'datetime', '', '', '', '', '', 33, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'canceledDate', 'datetime', '', '取消日期', 'datetime', '', '', '', '', '', 35, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'whitelist', 'text', '', '白名单', 'multi-select', '', 'user', '', '', '', 43, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'deleted', 'enum', '', '已删除', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 48, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'lifetime', 'char', '30', '项目周期', 'input', '', '', '', '', '', 3, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'output', 'text', '', '输出', 'textarea', '', '', '', '', '', 9, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'auth', 'char', '30', '权限控制', 'input', '', '', '', '', '', 10, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'path', 'varchar', '255', '路径', 'input', '', '', '0', '', '', 12, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'grade', 'tinyint', '3', '层级', 'integer', '', '', '0', '', '', 13, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'realBegan', 'date', '', '实际开始日期', 'date', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'realEnd', 'date', '', '实际完成日期', 'date', '', '', '', '', '', 18, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'version', 'smallint', '6', '版本', 'integer', '', '', '', '', '', 23, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'parentVersion', 'smallint', '6', '父版本', 'integer', '', '', '', '', '', 24, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'planDuration', 'int', '11', '计划周期天数', 'integer', '', '', '', '', '', 25, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'realDuration', 'int', '11', '实际周期天数', 'integer', '', '', '', '', '', 26, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'openedVersion', 'varchar', '20', '创建版本', 'input', '', '', '', '', '', 29, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'lastEditedBy', 'varchar', '30', '最后编辑人', 'select', '', 'user', '', '', '', 30, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'lastEditedDate', 'datetime', '', '最后编辑日期', 'datetime', '', '', '', '', '', 31, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'suspendedDate', 'date', '', '暂停日期', 'date', '', '', '', '', '', 36, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'vision', 'varchar', '10', '界面', 'input', '', '', 'rnd', '', '', 45, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'project', 'mediumint', '8', '所属项目集', 'input', '', '', '', '', '', 2, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'code', 'varchar', '45', '项目代号', 'input', '', '', '', '', '', 14, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'type', 'char', '30', '项目类型', 'select', '', '16', 'sprint', '', '', 3, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'model', 'char', '30', '项目管理方式', 'input', '', '45', '', '', '', 2, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'name', 'varchar', '90', '项目名称', 'input', '', '', '', '', '', 15, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'begin', 'date', '', '计划开始', 'date', '', '', '', '', '', 16, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'end', 'date', '', '计划完成', 'date', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'days', 'smallint', '5', '可用工作日', 'integer', '', '', '', '', '', 20, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'pri', 'enum', '', '优先级', 'select', '', '[1,2,3,4]', '1', '', '', 22, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'desc', 'text', '', '项目描述', 'richtext', '', '', '', '', '', 23, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'openedDate', 'datetime', '', '创建日期', 'datetime', '', '', '', '', '', 29, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'closedDate', 'datetime', '', '关闭日期', 'datetime', '', '', '', '', '', 34, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'canceledDate', 'datetime', '', '取消日期', 'datetime', '', '', '', '', '', 36, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'acl', 'char', '30', '访问控制', 'radio', '', '18', 'open', '', '', 43, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'whitelist', 'text', '', '项目白名单', 'multi-select', '', 'user', '', '', '', 44, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'deleted', 'enum', '', '已删除', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 49, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'lifetime', 'char', '30', '项目周期', 'input', '', '', '', '', '', 4, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'output', 'text', '', '输出', 'textarea', '', '', '', '', '', 10, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'auth', 'char', '30', '权限控制', 'input', '', '', '', '', '', 11, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'path', 'varchar', '255', '路径', 'input', '', '', '0', '', '', 13, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'grade', 'tinyint', '3', '层级', 'integer', '', '', '0', '', '', 14, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'realBegan', 'date', '', '实际开始日期', 'date', '', '', '', '', '', 18, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'realEnd', 'date', '', '实际完成日期', 'date', '', '', '', '', '', 19, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'version', 'smallint', '6', '版本', 'integer', '', '', '', '', '', 24, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'parentVersion', 'smallint', '6', '父版本', 'integer', '', '', '', '', '', 25, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'planDuration', 'int', '11', '计划周期天数', 'integer', '', '', '', '', '', 26, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'realDuration', 'int', '11', '实际周期天数', 'integer', '', '', '', '', '', 27, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'openedVersion', 'varchar', '20', '创建版本', 'input', '', '', '', '', '', 30, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'lastEditedBy', 'varchar', '30', '最后编辑人', 'select', '', 'user', '', '', '', 31, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'lastEditedDate', 'datetime', '', '最后编辑日期', 'datetime', '', '', '', '', '', 32, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'suspendedDate', 'date', '', '暂停日期', 'date', '', '', '', '', '', 37, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'vision', 'varchar', '10', '界面', 'input', '', '', 'rnd', '', '', 46, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'displayCards', 'smallint', '6', '每列最大卡片数', 'input', '', '', '0', '', '', 44, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'fluidBoard', 'enum', '', '列宽度', 'radio', '', '[\"\\u56fa\\u5b9a\\u5217\\u5bbd\",\"\\u81ea\\u9002\\u5e94\\u5217\\u5bbd\"]', '0', '', '', 45, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'project', 'mediumint', '8', '所属项目', 'input', '', '', '', '', '', 2, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'type', 'char', '30', '迭代类型', 'select', '', '16', 'sprint', '', '', 3, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'begin', 'date', '', '计划开始', 'date', '', '', '', '', '', 14, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'end', 'date', '', '计划完成', 'date', '', '', '', '', '', 15, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
@@ -176,31 +208,27 @@ REPLACE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `c
('execution', 'acl', 'char', '30', '访问控制', 'radio', '', '18', 'open', '', '', 41, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'whitelist', 'text', '', '白名单', 'multi-select', '', 'user', '', '', '', 42, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'deleted', 'enum', '', '已删除', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 47, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'type', 'char', '30', '类型', 'select', '', '16', 'sprint', '', '', 2, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'begin', 'date', '', '计划开始', 'date', '', '', '', '', '', 15, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'end', 'date', '', '计划完成', 'date', '', '', '', '', '', 16, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'days', 'smallint', '5', '可用工作日', 'integer', '', '', '', '', '', 19, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'pri', 'enum', '', '优先级', 'select', '', '[1,2,3,4]', '1', '', '', 21, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'desc', 'text', '', '项目集描述', 'richtext', '', '', '', '', '', 22, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'openedDate', 'datetime', '', '创建日期', 'datetime', '', '', '', '', '', 28, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'closedDate', 'datetime', '', '关闭日期', 'datetime', '', '', '', '', '', 33, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'canceledDate', 'datetime', '', '取消日期', 'datetime', '', '', '', '', '', 35, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'whitelist', 'text', '', '白名单', 'multi-select', '', 'user', '', '', '', 43, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'deleted', 'enum', '', '已删除', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 48, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'type', 'char', '30', '项目类型', 'select', '', '16', 'sprint', '', '', 3, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'model', 'char', '30', '项目管理方式', 'input', '', '45', '', '', '', 2, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'name', 'varchar', '90', '项目名称', 'input', '', '', '', '', '', 15, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'begin', 'date', '', '计划开始', 'date', '', '', '', '', '', 16, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'end', 'date', '', '计划完成', 'date', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'days', 'smallint', '5', '可用工作日', 'integer', '', '', '', '', '', 20, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'pri', 'enum', '', '优先级', 'select', '', '[1,2,3,4]', '1', '', '', 22, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'desc', 'text', '', '项目描述', 'richtext', '', '', '', '', '', 23, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'openedDate', 'datetime', '', '创建日期', 'datetime', '', '', '', '', '', 29, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'closedDate', 'datetime', '', '关闭日期', 'datetime', '', '', '', '', '', 34, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'canceledDate', 'datetime', '', '取消日期', 'datetime', '', '', '', '', '', 36, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'acl', 'char', '30', '访问控制', 'radio', '', '18', 'open', '', '', 43, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'whitelist', 'text', '', '项目白名单', 'multi-select', '', 'user', '', '', '', 44, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'deleted', 'enum', '', '已删除', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 49, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'lifetime', 'char', '30', '项目周期', 'input', '', '', '', '', '', 4, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'attribute', 'varchar', '30', '阶段类型', 'input', '', '', '0', '', '', 5, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'percent', 'float', '', '工作量占比', 'input', '', '', '0', '', '', 6, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'milestone', 'enum', '', '里程碑', 'radio', '', '[\"\\u662f\",\"\\u5426\"]', '0', '', '', 7, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'output', 'text', '', '输出', 'textarea', '', '', '', '', '', 8, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'auth', 'char', '30', '权限控制', 'input', '', '', '', '', '', 9, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'path', 'varchar', '255', '路径', 'input', '', '', '0', '', '', 10, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'grade', 'tinyint', '3', '层级', 'integer', '', '', '0', '', '', 11, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'realBegan', 'date', '', '实际开始日期', 'date', '', '', '', '', '', 16, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'realEnd', 'date', '', '实际完成日期', 'date', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'version', 'smallint', '6', '版本', 'integer', '', '', '', '', '', 22, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'parentVersion', 'smallint', '6', '父版本', 'integer', '', '', '', '', '', 23, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'planDuration', 'int', '11', '计划周期天数', 'integer', '', '', '', '', '', 24, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'realDuration', 'int', '11', '实际周期天数', 'integer', '', '', '', '', '', 25, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'openedVersion', 'varchar', '20', '创建版本', 'input', '', '', '', '', '', 28, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'lastEditedBy', 'varchar', '30', '最后编辑人', 'select', '', 'user', '', '', '', 29, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'lastEditedDate', 'datetime', '', '最后编辑日期', 'datetime', '', '', '', '', '', 30, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'suspendedDate', 'date', '', '暂停日期', 'date', '', '', '', '', '', 35, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'vision', 'varchar', '10', '界面', 'input', '', '', 'rnd', '', '', 44, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'displayCards', 'smallint', '6', '每列最大卡片数', 'input', '', '', '0', '', '', 46, 0, 0, '0', '0', '0', '1', 1, '', 'wangyidong', '2022-05-17 11:05:43', '', '0000-00-00 00:00:00'),
('execution', 'fluidBoard', 'enum', '', '列宽度', 'radio', '', '[\"\\u56fa\\u5b9a\\u5217\\u5bbd\",\"\\u81ea\\u9002\\u5e94\\u5217\\u5bbd\"]', '0', '', '', 47, 0, 0, '0', '0', '0', '1', 1, '', 'wangyidong', '2022-05-17 11:05:43', '', '0000-00-00 00:00:00'),
('build', 'project', 'mediumint', '8', '所属项目', 'select', '', '2', '0', '', '', 4, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('build', 'date', 'date', '', '打包日期', 'date', '', '', '', '', '', 9, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('build', 'desc', 'text', '', '描述', 'richtext', '', '', '', '', '', 13, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
@@ -221,6 +249,19 @@ REPLACE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `c
('bug', 'caseVersion', 'smallint', '6', '用例版本', 'integer', '', '', '', '', '', 46, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'lastEditedDate', 'datetime', '30', '修改日期', 'datetime', '', '', '', '', '', 58, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'deleted', 'enum', '', '已删除', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 59, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'confirmed', 'tinyint', '1', '是否确认', 'select', '', '[\"\\u662f\",\"\\u5426\"]', '0', '', '', 25, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'hardware', 'varchar', '30', '硬件', 'input', '', '', '', '', '', 20, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'feedbackBy', 'varchar', '100', '反馈者', 'input', '', '', '', '', '', 28, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'notifyEmail', 'varchar', '100', '通知邮箱', 'input', '', '', '', '', '', 29, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'result', 'mediumint', '8', '结果', 'input', '', '', '', '', '', 47, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'repo', 'mediumint', '8', '所属版本库', 'input', '', '', '', '', '', 48, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'mr', 'mediumint', '8', '合并请求', 'input', '', '', '', '', '', 49, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'entry', 'text', '', '代码路径', 'input', '', '', '', '', '', 50, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'lines', 'varchar', '10', '代码行', 'input', '', '', '', '', '', 51, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'v1', 'varchar', '40', '版本1', 'input', '', '', '', '', '', 52, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'v2', 'varchar', '40', '版本2', 'input', '', '', '', '', '', 53, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'repoType', 'varchar', '30', '版本库类型', 'input', '', '', '', '', '', 54, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'issueKey', 'varchar', '50', 'Sonarqube问题键值', 'input', '', '', '', '', '', 55, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'project', 'mediumint', '8', '所属项目', 'select', '', '2', '0', '', '', 2, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'parent', 'mediumint', '8', '父任务', 'select', '', '9', '0', '', '', 3, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'storyVersion', 'smallint', '6', '研发需求版本', 'integer', '', '', '1', '', '', 7, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
@@ -238,92 +279,19 @@ REPLACE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `c
('task', 'closedDate', 'datetime', '', '关闭时间', 'datetime', '', '', '', '', '', 34, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'lastEditedDate', 'datetime', '', '最后修改日期', 'datetime', '', '', '', '', '', 39, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'deleted', 'enum', '', '已删除', 'select', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 48, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'confirmed', 'tinyint', '1', '是否确认', 'select', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 25, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'lifetime', 'char', '30', 'lifetime', 'input', '', '', '', '', '', 4, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'lifetime', 'char', '30', 'lifetime', 'input', '', '', '', '', '', 3, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'designVersion', 'smallint', '6', '设计版本', 'integer', '', '', '', '', '', 8, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'attribute', 'varchar', '30', 'attribute', 'input', '', '', '0', '', '', 5, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'percent', 'float', '', 'percent', 'input', '', '', '0', '', '', 6, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'milestone', 'enum', '', 'milestone', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 7, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'output', 'text', '', 'output', 'textarea', '', '', '', '', '', 8, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'auth', 'char', '30', 'auth', 'input', '', '', '', '', '', 9, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'path', 'varchar', '255', 'path', 'input', '', '', '0', '', '', 10, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'grade', 'tinyint', '3', 'grade', 'integer', '', '', '0', '', '', 11, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'realBegan', 'date', '', '实际开始日期', 'date', '', '', '', '', '', 16, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'realEnd', 'date', '', '实际完成日期', 'date', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'version', 'smallint', '6', 'version', 'integer', '', '', '', '', '', 22, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'parentVersion', 'smallint', '6', 'parentVersion', 'integer', '', '', '', '', '', 23, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'planDuration', 'int', '11', 'planDuration', 'integer', '', '', '', '', '', 24, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'realDuration', 'int', '11', 'realDuration', 'integer', '', '', '', '', '', 25, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'openedVersion', 'varchar', '20', 'openedVersion', 'input', '', '', '', '', '', 28, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'lastEditedBy', 'varchar', '30', 'lastEditedBy', 'select', '', 'user', '', '', '', 29, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'lastEditedDate', 'datetime', '', 'lastEditedDate', 'datetime', '', '', '', '', '', 30, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'suspendedDate', 'date', '', 'suspendedDate', 'date', '', '', '', '', '', 35, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'vision', 'varchar', '10', 'vision', 'input', '', '', 'rnd', '', '', 44, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'displayCards', 'enum', '', 'displayCards', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 45, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'fluidBoard', 'enum', '', 'fluidBoard', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 46, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'output', 'text', '', 'output', 'textarea', '', '', '', '', '', 9, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'auth', 'char', '30', 'auth', 'input', '', '', '', '', '', 10, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'path', 'varchar', '255', 'path', 'input', '', '', '0', '', '', 12, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'grade', 'tinyint', '3', 'grade', 'integer', '', '', '0', '', '', 13, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'realBegan', 'date', '', 'realBegan', 'date', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'realEnd', 'date', '', 'realEnd', 'date', '', '', '', '', '', 18, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'version', 'smallint', '6', 'version', 'integer', '', '', '', '', '', 23, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'parentVersion', 'smallint', '6', 'parentVersion', 'integer', '', '', '', '', '', 24, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'planDuration', 'int', '11', 'planDuration', 'integer', '', '', '', '', '', 25, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'realDuration', 'int', '11', 'realDuration', 'integer', '', '', '', '', '', 26, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'openedVersion', 'varchar', '20', 'openedVersion', 'input', '', '', '', '', '', 29, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'lastEditedBy', 'varchar', '30', 'lastEditedBy', 'select', '', 'user', '', '', '', 30, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'lastEditedDate', 'datetime', '', 'lastEditedDate', 'datetime', '', '', '', '', '', 31, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'suspendedDate', 'date', '', 'suspendedDate', 'date', '', '', '', '', '', 36, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'vision', 'varchar', '10', 'vision', 'input', '', '', 'rnd', '', '', 45, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'displayCards', 'enum', '', 'displayCards', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 46, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('program', 'fluidBoard', 'enum', '', 'fluidBoard', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 47, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'lifetime', 'char', '30', '项目周期', 'input', '', '', '', '', '', 4, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'attribute', 'varchar', '30', '阶段类型', 'input', '', '', '0', '', '', 7, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'percent', 'float', '', '工作量占比', 'input', '', '', '0', '', '', 8, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'milestone', 'enum', '', '里程碑', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 9, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'output', 'text', '', '输出', 'textarea', '', '', '', '', '', 10, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'auth', 'char', '30', '权限控制', 'input', '', '', '', '', '', 11, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'path', 'varchar', '255', '路径', 'input', '', '', '0', '', '', 13, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'grade', 'tinyint', '3', '层级', 'integer', '', '', '0', '', '', 14, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'realBegan', 'date', '', '实际开始日期', 'date', '', '', '', '', '', 18, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'realEnd', 'date', '', '实际完成日期', 'date', '', '', '', '', '', 19, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'version', 'smallint', '6', '版本', 'integer', '', '', '', '', '', 24, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'parentVersion', 'smallint', '6', '父版本', 'integer', '', '', '', '', '', 25, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'planDuration', 'int', '11', '计划周期天数', 'integer', '', '', '', '', '', 26, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'realDuration', 'int', '11', '实际周期天数', 'integer', '', '', '', '', '', 27, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'openedVersion', 'varchar', '20', '创建版本', 'input', '', '', '', '', '', 30, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'lastEditedBy', 'varchar', '30', '最后编辑人', 'select', '', 'user', '', '', '', 31, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'lastEditedDate', 'datetime', '', '最后编辑日期', 'datetime', '', '', '', '', '', 32, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'suspendedDate', 'date', '', 'suspendedDate', 'date', '', '', '', '', '', 37, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'vision', 'varchar', '10', 'vision', 'input', '', '', 'rnd', '', '', 46, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'displayCards', 'enum', '', 'displayCards', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 47, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('project', 'fluidBoard', 'enum', '', 'fluidBoard', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 48, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'hardware', 'varchar', '30', '硬件', 'input', '', '', '', '', '', 20, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'feedbackBy', 'varchar', '100', '反馈者', 'input', '', '', '', '', '', 28, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'notifyEmail', 'varchar', '100', '通知邮箱', 'input', '', '', '', '', '', 29, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'result', 'mediumint', '8', '结果', 'input', '', '', '', '', '', 47, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'repo', 'mediumint', '8', '所属版本库', 'input', '', '', '', '', '', 48, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'mr', 'mediumint', '8', 'mr', 'input', '', '', '', '', '', 49, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'entry', 'text', '', 'entry', 'input', '', '', '', '', '', 50, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'lines', 'varchar', '10', '代码行', 'input', '', '', '', '', '', 51, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'v1', 'varchar', '40', '版本1', 'input', '', '', '', '', '', 52, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'v2', 'varchar', '40', '版本2', 'input', '', '', '', '', '', 53, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'repoType', 'varchar', '30', '版本库类型', 'input', '', '', '', '', '', 54, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'issueKey', 'varchar', '50', 'issueKey', 'input', '', '', '', '', '', 55, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'version', 'smallint', '6', '版本', 'integer', '', '', '', '', '', 21, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'planDuration', 'int', '11', '计划持续天数', 'integer', '', '', '', '', '', 35, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'realDuration', 'int', '11', '实际持续天数', 'integer', '', '', '', '', '', 36, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'activatedDate', 'datetime', '', '激活日期', 'datetime', '', '', '', '', '', 40, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'repo', 'mediumint', '8', 'repo', 'input', '', '', '', '', '', 41, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'mr', 'mediumint', '8', 'mr', 'input', '', '', '', '', '', 42, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'entry', 'text', '', 'entry', 'input', '', '', '', '', '', 43, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'lines', 'varchar', '10', 'lines', 'input', '', '', '', '', '', 44, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'v1', 'varchar', '40', 'v1', 'input', '', '', '', '', '', 45, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'v2', 'varchar', '40', 'v2', 'input', '', '', '', '', '', 46, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'repo', 'mediumint', '8', '所属版本库', 'input', '', '', '', '', '', 41, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'mr', 'mediumint', '8', '合并请求', 'input', '', '', '', '', '', 42, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'entry', 'text', '', '代码路径', 'input', '', '', '', '', '', 43, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'lines', 'varchar', '10', '代码行', 'input', '', '', '', '', '', 44, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'v1', 'varchar', '40', '版本1', 'input', '', '', '', '', '', 45, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'v2', 'varchar', '40', '版本2', 'input', '', '', '', '', '', 46, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'closedReason', 'varchar', '30', '关闭原因', 'select', '', 49, '', '', '', 37, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'vision', 'varchar', '10', 'vision', 'input', '', '', '', '', '', 47, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'vision', 'varchar', '10', '界面', 'input', '', '', '', '', '', 47, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('feedback', 'type', 'char', '30', '反馈类型', 'select', '', '', '', '', '', 4, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('feedback', 'notifyEmail', 'varchar', '100', '通知邮箱', 'input', '', '', '', '', '', 9, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('feedback', 'faq', 'mediumint', '8', 'FAQ', 'input', '', '', '', '', '', 11, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
@@ -342,17 +310,49 @@ REPLACE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `c
('testcase', 'precondition', 'text', '', '前置条件', 'textarea', '', '', '', '', '', 5, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('testcase', 'subStatus', 'varchar', '30', '子状态', 'select', '', '', '', '', '', 17, 0, 0, '0', '0', '0', '0', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00');
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='projectModel' ORDER BY id DESC LIMIT 1) WHERE `module`='project' AND `field`='model';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackType' ORDER BY id DESC LIMIT 1) WHERE `module`='feedback' AND `field`='type';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackSolution' ORDER BY id DESC LIMIT 1) WHERE `module`='feedback' AND `field`='solution';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='storyClosedReason' ORDER BY id DESC LIMIT 1) WHERE `module`='story' AND `field`='closedReason';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='taskReason' ORDER BY id DESC LIMIT 1) WHERE `module`='task' AND `field`='closedReason';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='programs' ORDER BY id DESC LIMIT 1), `control`='select' WHERE `module`='program' AND `field`='parent';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='programs' ORDER BY id DESC LIMIT 1), `control`='select' WHERE `module`='project' AND `field`='parent';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='projects' ORDER BY id DESC LIMIT 1), `control`='select' WHERE `module`='execution' AND `field`='parent';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackclosedReason' ORDER BY id DESC LIMIT 1), `control`='select' WHERE `module`='feedback' AND `field`='closedReason';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='testsuiteAuth' ORDER BY id DESC LIMIT 1), `control`='radio' WHERE `module`='testsuite' AND `field`='type';
UPDATE `zt_workflowfield` SET `control` = 'radio' WHERE `module` = 'program' and `field` = 'deleted';
UPDATE `zt_workflowfield` SET `type` = 'char', `length` = '30', `control` = 'radio' WHERE `module` = 'program' and `field` = 'type';
UPDATE `zt_workflowfield` SET `control` = 'date' WHERE `module` = 'program' and `field` = 'begin';
UPDATE `zt_workflowfield` SET `control` = 'date' WHERE `module` = 'program' and `field` = 'end';
UPDATE `zt_workflowfield` SET `control` = 'integer' WHERE `module` = 'program' and `field` = 'days';
UPDATE `zt_workflowfield` SET `control` = 'select', `options` = '[1,2,3,4]' WHERE `module` = 'program' and `field` = 'pri';
UPDATE `zt_workflowfield` SET `control` = 'richtext' WHERE `module` = 'program' and `field` = 'desc';
UPDATE `zt_workflowfield` SET `control` = 'datetime' WHERE `module` = 'program' and `field` = 'openedDate';
UPDATE `zt_workflowfield` SET `control` = 'datetime' WHERE `module` = 'program' and `field` = 'closedDate';
UPDATE `zt_workflowfield` SET `control` = 'datetime' WHERE `module` = 'program' and `field` = 'canceledDate';
UPDATE `zt_workflowfield` SET `type` = 'char', `length` = '30', `control`='radio' WHERE `module` = 'program' and `field` = 'acl';
UPDATE `zt_workflowfield` SET `control`='radio' WHERE `module` = 'product' and `field` = 'acl';
UPDATE `zt_workflowfield` SET `control` = 'multi-select', `options` = 'user' WHERE `module` = 'program' and `field` = 'whitelist';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='projectModel' ORDER BY `id` DESC LIMIT 1) WHERE `module`='project' AND `field`='model';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackType' ORDER BY `id` DESC LIMIT 1) WHERE `module`='feedback' AND `field`='type';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackSolution' ORDER BY `id` DESC LIMIT 1) WHERE `module`='feedback' AND `field`='solution';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='taskReason' ORDER BY `id` DESC LIMIT 1) WHERE `module`='task' AND `field`='closedReason';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='storyClosedReason' ORDER BY `id` DESC LIMIT 1) WHERE `module`='story' AND `field`='closedReason';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='programs' ORDER BY `id` DESC LIMIT 1), `control`='select' WHERE `module`='program' AND `field`='parent';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='programs' ORDER BY `id` DESC LIMIT 1), `control`='select' WHERE `module`='project' AND `field`='parent';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='projects' ORDER BY `id` DESC LIMIT 1), `control`='select' WHERE `module`='execution' AND `field`='parent';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackclosedReason' ORDER BY `id` DESC LIMIT 1), `control`='select' WHERE `module`='feedback' AND `field`='closedReason';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='testsuiteAuth' ORDER BY `id` DESC LIMIT 1), `control`='radio' WHERE `module`='testsuite' AND `field`='type';
UPDATE `zt_workflowaction` SET `show`='direct' WHERE `buildin`=1;
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'product' and `action` = 'all' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `type` = 'batch', `position` = 'browse' WHERE `module` = 'product' and `action` = 'batchedit' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'product' and `action` = 'browse' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `show` = 'direct' WHERE `module` = 'product' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `type` = 'batch', `position` = 'browse' WHERE `module` = 'productplan' and `action` = 'batchedit' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'productplan' and `action` = 'browse' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `show` = 'direct' WHERE `module` = 'productplan' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'release' and `action` = 'browse' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `show` = 'direct' WHERE `module` = 'release' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `type` = 'batch', `position` = 'browseandview' WHERE `module` = 'story' and `action` = 'batchcreate' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `type` = 'batch' WHERE `module` = 'story' and `action` = 'batchedit' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'story' and `action` = 'browse' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'story' and `action` = 'exporttemplate' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'story' and `action` = 'import' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `position` = 'browse' WHERE `module` = 'story' and `action` = 'view' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `show` = 'direct' WHERE `module` = 'story' and `vision` = 'rnd' and action NOT IN ('exporttemplate', 'import');
UPDATE `zt_workflowaction` SET `show` = 'direct' WHERE `module` = 'program' and `vision` = 'rnd';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='project' AND `action`='browse';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='project' AND `action`='create';
UPDATE `zt_workflowaction` SET `type`='batch', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='project' AND `action`='batchedit';
@@ -377,7 +377,7 @@ UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `sho
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='execution' AND `action`='all';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='task' AND `action`='browse';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='task' AND `action`='create';
UPDATE `zt_workflowaction` SET `type`='batch', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='task' AND `action`='batchcreate';
UPDATE `zt_workflowaction` SET `type`='batch', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='task' AND `action`='batchcreate';
UPDATE `zt_workflowaction` SET `type`='batch', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='task' AND `action`='batchedit';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='exporttemplate';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='import';
@@ -416,43 +416,9 @@ UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `sho
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='bug' AND `action`='resolve';
UPDATE `zt_workflowaction` SET `type`='batch', `position`='browse', `show`='direct', `open`='none', `layout`='normal' WHERE `module`='bug' AND `action`='batchconfirm';
UPDATE `zt_workflowaction` SET `type`='batch', `position`='browse', `show`='direct', `open`='none', `layout`='normal' WHERE `module`='bug' AND `action`='batchresolve';
UPDATE `zt_workflowaction` SET `type`='batch' WHERE `module`IN ('feedback','caselib','testsuite','testtask','testcase') AND `action` IN ('admin','browse','batchedit','batchcreate','import','showimport');
UPDATE `zt_workflowaction` SET `type`='batch' WHERE `module`IN ('feedback','caselib','testsuite','testtask','testcase') AND `action` IN ('batchedit','batchcreate');
UPDATE `zt_workflowaction` SET `position`='browse' WHERE `module`IN ('feedback','caselib','testsuite','testtask','testcase') AND `action` IN ('batchedit','batchcreate','import','showimport');
UPDATE `zt_workflowfield` SET `control` = 'radio' WHERE `module` = 'program' and `field` = 'deleted';
UPDATE `zt_workflowfield` SET `control` = 'radio', `type` = 'char', `length` = '30' WHERE `module` = 'program' and `field` = 'type';
UPDATE `zt_workflowfield` SET `control` = 'date' WHERE `module` = 'program' and `field` = 'begin';
UPDATE `zt_workflowfield` SET `control` = 'date' WHERE `module` = 'program' and `field` = 'end';
UPDATE `zt_workflowfield` SET `control` = 'integer' WHERE `module` = 'program' and `field` = 'days';
UPDATE `zt_workflowfield` SET `control` = 'select', `options` = '[1,2,3,4]' WHERE `module` = 'program' and `field` = 'pri';
UPDATE `zt_workflowfield` SET `control` = 'richtext' WHERE `module` = 'program' and `field` = 'desc';
UPDATE `zt_workflowfield` SET `control` = 'datetime' WHERE `module` = 'program' and `field` = 'openedDate';
UPDATE `zt_workflowfield` SET `control` = 'datetime' WHERE `module` = 'program' and `field` = 'closedDate';
UPDATE `zt_workflowfield` SET `control` = 'datetime' WHERE `module` = 'program' and `field` = 'canceledDate';
UPDATE `zt_workflowfield` SET `type` = 'char', `length` = '30', `control`='radio' WHERE `module` = 'program' and `field` = 'acl';
UPDATE `zt_workflowfield` SET `control`='radio' WHERE `module` = 'product' and `field` = 'acl';
UPDATE `zt_workflowfield` SET `control` = 'multi-select', `options` = 'user' WHERE `module` = 'program' and `field` = 'whitelist';
REPLACE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `control`, `expression`, `options`, `default`, `rules`, `placeholder`, `order`, `searchOrder`, `exportOrder`, `canExport`, `canSearch`, `isValue`, `readonly`, `buildin`, `desc`, `createdBy`, `createdDate`, `editedBy`, `editedDate`) VALUES
('program', 'lifetime', 'char', '30', '项目周期', 'input', '', '', '', '', '', 29, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'output', 'text', '', '输出', 'textarea', '', '', '', '', '', 30, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'auth', 'char', '30', '权限控制', 'input', '', '', '', '', '', 31, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'path', 'varchar', '255', '路径', 'input', '', '', '', '', '', 32, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'grade', 'tinyint', '3', '层级', 'integer', '', '', '', '', '', 33, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'realBegan', 'date', '', '实际开始日期', 'date', '', '', '', '', '', 34, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'realEnd', 'date', '', '实际完成日期', 'date', '', '', '', '', '', 35, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'version', 'smallint', '6', '版本', 'integer', '', '', '', '', '', 36, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'parentVersion', 'smallint', '6', '父版本', 'integer', '', '', '', '', '', 37, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'planDuration', 'smallint', '6', '计划周期天数', 'integer', '', '', '', '', '', 38, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'realDuration', 'smallint', '6', '实际周期天数', 'integer', '', '', '', '', '', 39, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'openedVersion', 'smallint', '6', '创建版本', 'integer', '', '', '', '', '', 40, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'lastEditedBy', 'varchar', '30', '最后编辑人', 'select', '', 'user', '', '', '', 41, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'lastEditedDate', 'datetime', '', '最后编辑日期', 'datetime', '', '', '', '', '', 42, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'suspendedDate', 'date', '', 'suspendedDate', 'date', '', '', '', '', '', 43, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'vision', 'varchar', '10', 'vision', 'input', '', '', 'rnd', '', '', 44, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'displayCards', 'enum', '', 'displayCards', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 45, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00'),
('program', 'fluidBoard', 'enum', '', 'fluidBoard', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 46, 0, 0, '0', '0', '0', '1', 1, '', '', '2022-04-19 10:14:25', '', '0000-00-00 00:00:00');
UPDATE `zt_workflowaction` SET `position`='browse' WHERE `action` IN ('view','exporttemplate');
UPDATE `zt_workflowaction` SET `position`='browse' WHERE `action`='create' AND `module` IN ('testtask','feedback');
@@ -466,9 +432,10 @@ UPDATE `zt_workflowaction` SET `type` ='single' WHERE `action`='browse' AND mod
UPDATE `zt_workflowaction` SET `method`='browse' WHERE module='product' and `action` = 'all';
UPDATE `zt_workflowaction` SET `type` ='single' WHERE `action`='browse' AND `type`='batch' AND `buildin`=1;
UPDATE `zt_workflowaction` SET `show`='direct' WHERE `buildin`=1;
UPDATE `zt_workflowlayout` SET `mobileShow`='0' WHERE `mobileShow`='1' AND `module` IN('product', 'story', 'productplan', 'release', 'project', 'task', 'build', 'bug', 'testcase', 'testtask', 'testsuite', 'caselib', 'feedback');
UPDATE `zt_workflowfield` SET `canSearch` = '1' WHERE `buildin` = '1';
UPDATE `zt_project` SET `status` = 'doing' WHERE `type` = 'program' and `status` = 'wait' and `realBegan` != '0000-00-00' and `realBegan` != '';
UPDATE `zt_project` SET `status` = 'doing' WHERE `type` = 'program' and `status` = 'wait' and `realBegan` != '0000-00-00';
CREATE TABLE `zt_approval` (
`id` mediumint(8) NOT NULL AUTO_INCREMENT,
+7
View File
@@ -0,0 +1,7 @@
ALTER TABLE `zt_task` ADD `fromIssue` mediumint(8) unsigned NOT NULL DEFAULT '0' AFTER `fromBug`;
ALTER TABLE `zt_kanbanspace` ADD COLUMN `activatedBy` char(30) NOT NULL AFTER `closedDate`;
ALTER TABLE `zt_kanbanspace` ADD COLUMN `activatedDate` datetime NOT NULL AFTER `activatedBy`;
ALTER TABLE `zt_kanban` ADD COLUMN `activatedBy` char(30) NOT NULL AFTER `closedDate`;
ALTER TABLE `zt_kanban` ADD COLUMN `activatedDate` datetime NOT NULL AFTER `activatedBy`;
Regular → Executable
+5
View File
@@ -760,6 +760,8 @@ CREATE TABLE `zt_kanbanspace` (
`lastEditedDate` datetime NOT NULL,
`closedBy` char(30) NOT NULL,
`closedDate` datetime NOT NULL,
`activatedBy` char(30) NOT NULL,
`activatedDate` datetime NOT NULL,
`deleted` enum('0', '1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
@@ -786,6 +788,8 @@ CREATE TABLE `zt_kanban` (
`lastEditedDate` datetime NOT NULL,
`closedBy` char(30) NOT NULL,
`closedDate` datetime NOT NULL,
`activatedBy` char(30) NOT NULL,
`activatedDate` datetime NOT NULL,
`deleted` enum('0', '1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
@@ -1457,6 +1461,7 @@ CREATE TABLE IF NOT EXISTS `zt_task` (
`storyVersion` smallint(6) NOT NULL default '1',
`designVersion` smallint(6) unsigned NOT NULL,
`fromBug` mediumint(8) unsigned NOT NULL default '0',
`fromIssue` mediumint(8) unsigned NOT NULL default '0',
`name` varchar(255) NOT NULL,
`type` varchar(20) NOT NULL,
`pri` tinyint(3) unsigned NOT NULL default '0',
+43 -1
View File
@@ -1,7 +1,49 @@
2022-05-06 17.0.beta1
修复的bug
11398 批量移除需求的权限无法单独设置
17341 经典模式下研发需求分解任务时同上模块之后相关需求联动错误
14677 产品汇总表不应该统计父需求
16176 编辑用户密码小于系统设定也可以保存成功
16424 项目权限控制选择重新定义不生效
16648 项目列表中项目名称完全折叠隐藏
17448 草稿状态需求先关闭再激活后无法进行后续操作
17976 复制bug不能修改【所属项目】和【所属迭代】
18756 专业研发看板中移除白名单用户后该用户还可以访问看板
19745 需求接口参数修改
19841 创建瀑布类型的项目,设置阶段时权限设置没有继承项目权限
19860 富文本框里面 % 这个符号被过滤了
20015 维护项目的基础信息字段团队成员会变化
20043 父需求变更后无法进行评审
20175 搜索框内输入多个id且结尾为英文逗号时有报错
20385 提Bug弹窗切换产品或分支时点击创建版本弹窗有报错
20591 联系人列表删除列表名称点击保存有报错
20724 升级后执行关联需求报错
20742 不填写用户名保存后再补充用户名登录用户没有权限
21006 一个需求拆分为多个研发任务和测试任务且研发任务有执行开始状态后,需求状态被置为了已立项
完成的需求
32522 回收站增加检索标签
32387 旗舰版安装向导页面检测到数据库环境变量后跳过数据库配置页面
32343 产品发布的日期不做限制
31983 自定义任务必填项时增加所属模块选项
31603 参与需求评审的每个人都可以在我的地盘待评审列表看到
31577 专业研发看板中需求泳道需求的拖动规则
31576 Scrum看板需求泳道的需求卡片可以进行拖动
31551 更改燃尽图的更新逻辑
31367 执行切换组件中瀑布项目的子阶段展现方式优化
31365 执行切换组件中瀑布的阶段按正序排列,敏捷的执行按倒序排列
30783 通用看板中导入的卡片可以执行更多操作
30438 关闭执行前更新燃尽图数据
30104 看板中的横向的滚动条采用执行看板中的全局滚动条
29788 项目列表增加搜索功能
29787 产品列表增加搜索功能
29786 项目集列表增加搜索功能
29577 产品列表增加分页功能
29215 文档库的目录中文档和目录支持拖动排序功能
28961 产品的发布列表增加分页功能
28564 项目集列表页面增加分页功能
28363 切换项目后的页面保持和切换前的页面一致
27850 批量修改执行所属项目时提示用户该操作的影响
15239 Bug搜索条件中增加按关联需求搜索字段
2022-03-24 16.5
修复的bug
@@ -7,6 +7,7 @@ $lang->execution->createKanban = 'Create Kanban';
$lang->execution->noExecution = "No Executions.";
$lang->execution->importTask = 'Import Tsak';
$lang->execution->batchCreateTask = 'Batch Create Task';
$lang->execution->linkStory = "Create {$lang->SRCommon}";
$lang->execution->kanbanGroup['default'] = 'Default';
$lang->execution->kanbanGroup['story'] = 'Target';
@@ -24,4 +25,3 @@ $lang->execution->icons['grouptask'] = 'sitemap';
$lang->execution->aclList['private'] = "Private (Accessible to team members and project leaders)";
$lang->execution->common = 'Project Execution';
$lang->execution->gantt = 'Gantt Chart';
+38 -6
View File
@@ -617,6 +617,20 @@ class baseRouter
*/
public function setSuperVars()
{
$URI = $_SERVER['REQUEST_URI'];
if(strpos($URI, '?') !== false)
{
$parsedURL = parse_url($URI);
if(isset($parsedURL['query']))
{
parse_str($parsedURL['query'], $parsedQuery);
foreach($parsedQuery as $key => $value)
{
if(!isset($_GET[$key])) $_GET[$key] = $value;
}
}
}
$this->post = new super('post');
$this->get = new super('get');
$this->server = new super('server');
@@ -724,7 +738,7 @@ class baseRouter
*/
public function getInstalledVersion()
{
$version = $this->dbh->query("SELECT value FROM " . TABLE_CONFIG . " WHERE owner = 'system' AND `key` = 'version' LIMIT 1")->fetch();
$version = $this->dbh->query("SELECT value FROM " . TABLE_CONFIG . " WHERE `owner` = 'system' AND `key` = 'version' AND `module` = 'common' AND `section` = 'global' LIMIT 1")->fetch();
$version = $version ? $version->value : '0.3.beta'; // No version, set as 0.3.beta.
if($version == '3.0.stable') $version = '3.0'; // convert 3.0.stable to 3.0.
return $version;
@@ -987,7 +1001,11 @@ class baseRouter
$this->sessionID = isset($ztSessionHandler) ? $ztSessionHandler->getSessionID() : session_id();
if(isset($_GET[$this->config->sessionVar])) helper::restartSession($_GET[$this->config->sessionVar]);
if(isset($_GET[$this->config->sessionVar]))
{
helper::restartSession($_GET[$this->config->sessionVar]);
$this->sessionID = isset($ztSessionHandler) ? $ztSessionHandler->getSessionID() : session_id();
}
define('SESSION_STARTED', true);
}
@@ -3153,9 +3171,7 @@ class ztSessionHandler
($this->tagID and file_exists($this->rawFile)) ? copy($this->rawFile, $sessFile) : touch($sessFile);
}
$sessContent = (string) file_get_contents($sessFile);
if(!file_exists($this->rawFile) and strpos($sessContent, 'user|') !== false) copy($sessFile, $this->rawFile);
return $sessContent;
return (string) file_get_contents($sessFile);
}
/**
@@ -3169,7 +3185,23 @@ class ztSessionHandler
public function write($id, $sessData)
{
$sessFile = $this->getSessionFile($id);
if(file_put_contents($sessFile, $sessData)) return true;
if(file_put_contents($sessFile, $sessData))
{
if(strpos($sessData, 'user|') !== false)
{
if(file_exists($this->rawFile))
{
$rawSessContent = (string) file_get_contents($this->rawFile);
if(strpos($rawSessContent, 'user|') === false) copy($sessFile, $this->rawFile);
}
else
{
copy($sessFile, $this->rawFile);
}
}
return true;
}
return false;
}
+13 -6
View File
@@ -63,13 +63,16 @@ class model extends baseModel
* @param string $type
* @param string $icon
* @param string $target
* @param string $misc
* @param string $class
* @param bool $onlyBody
* @param string $misc
* @param string $title
* @param bool $returnHtml
* @access public
* @return string
*/
public function buildMenu($moduleName, $methodName, $params, $data, $type = 'view', $icon = '', $target = '', $class = '', $onlyBody = false, $misc = '' , $title = '')
public function buildMenu($moduleName, $methodName, $params, $data, $type = 'view', $icon = '', $target = '', $class = '', $onlyBody = false, $misc = '' , $title = '', $returnHtml = true)
{
if(strpos($moduleName, '.') !== false) list($appName, $moduleName) = explode('.', $moduleName);
@@ -115,6 +118,8 @@ class model extends baseModel
if(method_exists($this, 'isClickable')) $enabled = $this->isClickable($data, $method, $module);
}
if(!$returnHtml) return $enabled;
$html = '';
$type = $type == 'browse' ? 'list' : 'button';
$html = common::buildIconButton($module, $method, $params, $data, $type, $icon, $target, $class, $onlyBody, $misc, $title, '', $enabled);
@@ -139,6 +144,7 @@ class model extends baseModel
if(strpos($module, '.') !== false) list($appName, $moduleName) = explode('.', $module);
static $actions;
static $relations;
if(empty($actions))
{
$actions = $this->dao->select('*')->from(TABLE_WORKFLOWACTION)
@@ -149,6 +155,7 @@ class model extends baseModel
->orderBy('order_asc')
->fetchAll();
}
if(empty($relations)) $relations = $this->dao->select('next, actions')->from(TABLE_WORKFLOWRELATION)->where('prev')->eq($moduleName)->fetchPairs();
$menu = '';
if($show)
@@ -157,7 +164,7 @@ class model extends baseModel
{
if(strpos($action->position, $type) === false || $action->show != $show) continue;
$menu .= $this->loadModel('flow')->buildActionMenu($moduleName, $action, $data, $type);
$menu .= $this->loadModel('flow')->buildActionMenu($moduleName, $action, $data, $type, $relations);
}
}
else
@@ -167,8 +174,8 @@ class model extends baseModel
{
if(strpos($action->position, $type) === false) continue;
if($type == 'view' || $action->show == 'direct') $menu .= $this->loadModel('flow')->buildActionMenu($moduleName, $action, $data, $type);
if($type == 'browse' && $action->show == 'dropdownlist') $dropdownMenu .= $this->loadModel('flow')->buildActionMenu($moduleName, $action, $data, $type);
if($type == 'view' || $action->show == 'direct') $menu .= $this->loadModel('flow')->buildActionMenu($moduleName, $action, $data, $type, $relations);
if($type == 'browse' && $action->show == 'dropdownlist') $dropdownMenu .= $this->loadModel('flow')->buildActionMenu($moduleName, $action, $data, $type, $relations);
}
if($type == 'browse' && $dropdownMenu)
@@ -293,6 +300,6 @@ class model extends baseModel
}
$flow = $this->loadModel('workflow')->getByModule($moduleName);
if($flow && $action) $this->loadModel('workflowhook')->execute($flow, $action, $objectID);
if($flow && $action) return $this->loadModel('workflowhook')->execute($flow, $action, $objectID);
}
}
+28 -28
View File
@@ -181,54 +181,54 @@ class dao extends baseDAO
}
/**
* check workflow field rule.
* Check workFlow field rule.
*
* @access public
* @return object the dao object self.
*/
public function checkflow()
public function checkFlow()
{
global $app, $config;
global $app, $config, $lang;
if(!isset($config->bizVersion)) return $this;
$module = $app->getmodulename();
$method = $app->getmethodname();
$module = $app->getModuleName();
$method = $app->getMethodName();
$flowaction = $this->dbh->query("select * from " . TABLE_WORKFLOWACTION . " where `module` = '{$module}' and `action` = '{$method}' and `buildin` = '1' and `extensiontype` = 'extend'")->fetch(PDO::FETCH_OBJ);
if(!$flowaction) return $this;
$flowAction = $this->dbh->query("SELECT * FROM " . TABLE_WORKFLOWACTION . " WHERE `module` = '{$module}' AND `action` = '{$method}' AND `buildin` = '1' AND `extensionType` = 'extend'")->fetch(PDO::FETCH_OBJ);
if(!$flowAction) return $this;
$flowfields = $this->dbh->query("select t2.name,t2.rules,t2.control,t2.field,t1.layoutrules from " . TABLE_WORKFLOWLAYOUT . " as t1 left join " . TABLE_WORKFLOWFIELD . " as t2 on t1.module = t2.module and t1.field = t2.field where t1.module = '{$module}' and t1.action = '{$method}' and t1.readonly = '0'")->fetchall();
if(!$flowfields) return $this;
$flowFields = $this->dbh->query("SELECT t2.name,t2.rules,t2.control,t2.field,t1.layoutRules FROM " . TABLE_WORKFLOWLAYOUT . " AS t1 LEFT JOIN " . TABLE_WORKFLOWFIELD . " AS t2 ON t1.module = t2.module AND t1.field = t2.field WHERE t1.module = '{$module}' AND t1.action = '{$method}' AND t1.readonly = '0'")->fetchAll();
if(!$flowFields) return $this;
$rules = array();
$rawrules = $this->dbh->query("select * from " . TABLE_WORKFLOWRULE)->fetchall();
foreach($rawrules as $rule) $rules[$rule->id] = $rule;
$rawRules = $this->dbh->query("SELECT * FROM " . TABLE_WORKFLOWRULE)->fetchAll();
foreach($rawRules as $rule) $rules[$rule->id] = $rule;
foreach($flowfields as $key => $field)
foreach($flowFields as $key => $field)
{
if(!$field)
{
unset($flowfields[$key]);
unset($flowFields[$key]);
continue;
}
$ruleids = explode(',', trim($field->rules, ',') . ',' . trim($field->layoutrules, ','));
$ruleids = array_unique($ruleids);
$ruleIDs = explode(',', trim($field->rules, ',') . ',' . trim($field->layoutRules, ','));
$ruleIDs = array_unique($ruleIDs);
$fieldrules = array();
foreach($ruleids as $ruleid)
$fieldRules = array();
foreach($ruleIDs as $ruleID)
{
if(!$ruleid || !isset($rules[$ruleid])) continue;
if(!$ruleID || !isset($rules[$ruleID])) continue;
$fieldrules[] = $rules[$ruleid];
$fieldRules[] = $rules[$ruleID];
}
$field->ruledata = $fieldrules;
$field->rules = join(',', $ruleids);
$field->ruleData = $fieldRules;
$field->rules = join(',', $ruleIDs);
}
return $this->checkextend($flowfields);
return $this->checkExtend($flowFields);
}
/**
@@ -239,24 +239,24 @@ class dao extends baseDAO
* @access public
* @return object the dao object self
*/
public function checkextend($fields)
public function checkExtend($fields)
{
global $lang;
if(!$fields) return $this;
foreach($fields as $field)
{
/* if the field don't have rule, don't check it. */
/* If the field don't have rule, don't check it. */
if(empty($field->rules)) continue;
if($field->control == 'file')
{
foreach($field->ruledata as $rule)
foreach($field->ruleData as $rule)
{
if(empty($rule)) continue;
if($rule->type != 'system' || $rule->rule != 'notempty') continue;
$files = !empty($_files[$field->field]) ? $_files[$field->field] : '';
$files = !empty($_FILES[$field->field]) ? $_FILES[$field->field] : '';
if(empty($files)) dao::$errors[$field->field][] = sprintf($lang->error->notempty, $field->name);
break;
}
@@ -265,8 +265,8 @@ class dao extends baseDAO
if(!isset($this->sqlobj->data->{$field->field})) $this->sqlobj->data->{$field->field} = false;
/* check rules of fields. */
foreach($field->ruledata as $rule)
/* Check rules of fields. */
foreach($field->ruleData as $rule)
{
if(empty($rule)) continue;
+2 -1
View File
@@ -397,7 +397,8 @@ class bug extends control
$this->action->create('todo', $output['todoID'], 'finished', '', "BUG:$bugID");
}
$this->executeHooks($bugID);
$message = $this->executeHooks($bugID);
if($message) $this->lang->saveSuccess = $message;
/* Return bug id when call the API. */
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $bugID));
+3
View File
@@ -34,9 +34,12 @@ $lang->bug->browser = 'Browser';
$lang->bug->hardware = 'Hardware';
$lang->bug->result = 'Result';
$lang->bug->repo = 'Repo';
$lang->bug->mr = 'Merge Request';
$lang->bug->entry = 'Code Path';
$lang->bug->lines = 'Lines';
$lang->bug->v1 = 'Version A';
$lang->bug->v2 = 'Version B';
$lang->bug->issueKey = 'Sonarqube Issue Key';
$lang->bug->repoType = 'Repo Type';
$lang->bug->steps = 'Repro Steps';
$lang->bug->status = 'Status';
+3
View File
@@ -34,9 +34,12 @@ $lang->bug->browser = '浏览器';
$lang->bug->hardware = '硬件';
$lang->bug->result = '结果';
$lang->bug->repo = '所属版本库';
$lang->bug->mr = '合并请求';
$lang->bug->entry = '代码路径';
$lang->bug->lines = '代码行';
$lang->bug->v1 = '版本1';
$lang->bug->v2 = '版本2';
$lang->bug->issueKey = 'Sonarqube问题键值';
$lang->bug->repoType = '版本库类型';
$lang->bug->steps = '重现步骤';
$lang->bug->status = 'Bug状态';
+1
View File
@@ -2792,6 +2792,7 @@ class bugModel extends model
->orWhere('t2.spec')->like("%$searchValue%")
->orWhere('t2.verify')->like("%$searchValue%")
->fetchPairs('id');
if(empty($story)) $story = array(0);
$bugQuery = preg_replace("/`story`[ ]+(NOT[ ]*)?LIKE[ ]+'%$searchValue%'/Ui", '`story` $1 IN (' . implode(',', $story) .')', $bugQuery);
}
+3 -18
View File
@@ -131,12 +131,7 @@
<td class='<?php echo zget($visibleFields, 'keywords', 'hidden')?>'><?php echo html::input("keywords[$i]", '', "class='form-control'");?></td>
<?php
$this->loadModel('flow');
foreach($extendFields as $extendField)
{
$object = new stdclass();
$object->{$extendField->field} = $extendField->default;
echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, $object, $extendField->field . "[$i]") . "</td>";
}
foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[$i]") . "</td>";
?>
</tr>
<?php $i++;?>
@@ -186,12 +181,7 @@
<td class='<?php echo zget($visibleFields, 'keywords', 'hidden')?>'><?php echo html::input("keywords[$i]", '', "class='form-control'");?></td>
<?php
$this->loadModel('flow');
foreach($extendFields as $extendField)
{
$object = new stdclass();
$object->{$extendField->field} = $extendField->default;
echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, $object, $extendField->field . "[$i]") . "</td>";
}
foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[$i]") . "</td>";
?>
</tr>
<?php endfor;?>
@@ -240,12 +230,7 @@
<td class='<?php echo zget($visibleFields, 'keywords', 'hidden')?>'><?php echo html::input("keywords[%s]", '', "class='form-control'");?></td>
<?php
$this->loadModel('flow');
foreach($extendFields as $extendField)
{
$object = new stdclass();
$object->{$extendField->field} = $extendField->default;
echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, $object, $extendField->field . "[%s]") . "</td>";
}
foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[%s]") . "</td>";
?>
</tr>
</tbody>
+6 -3
View File
@@ -38,7 +38,8 @@ class build extends control
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->loadModel('action')->create('build', $buildID, 'opened');
$this->executeHooks($buildID);
$message = $this->executeHooks($buildID);
if($message) $this->lang->saveSuccess = $message;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $buildID));
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.loadExecutionBuilds($executionID, $buildID)")); // Code for task #5126.
@@ -130,7 +131,8 @@ class build extends control
if(!empty($changes)) $this->action->logHistory($actionID, $changes);
}
$this->executeHooks($buildID);
$message = $this->executeHooks($buildID);
if($message) $this->lang->saveSuccess = $message;
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('view', "buildID=$buildID")));
}
@@ -316,7 +318,8 @@ class build extends control
$build = $this->build->getById($buildID);
$this->build->delete(TABLE_BUILD, $buildID);
$this->executeHooks($buildID);
$message = $this->executeHooks($buildID);
if($message) $response['message'] = $message;
/* if ajax request, send result. */
if($this->server->ajax)
+33 -6
View File
@@ -526,20 +526,47 @@ class buildModel extends model
*
* @param object $build
* @param string $type
* @param string $extra
* @access public
* @return string
*/
public function buildOperateMenu($build, $type = 'view')
public function buildOperateMenu($build, $type = 'view', $extra = '')
{
$canBeChanged = common::canBeChanged('build', $build);
if($build->deleted || !$canBeChanged) return '';
$extraParams = array();
if($extra) parse_str($extra, $extraParams);
$menu = '';
$params = "buildID=$build->id";
$menu .= $this->buildFlowMenu('build', $build, 'view', 'direct');
$menu .= $this->buildMenu('build', 'edit', $params, $build, $type);
$menu .= $this->buildMenu('build', 'delete', $params, $build, $type, 'trash', 'hiddenwin');
global $app;
$tab = $app->tab;
if($type == 'browse')
{
$executionID = $tab == 'execution' ? $extraParams['executionID'] : $build->execution;
if(common::hasPriv('build', 'linkstory') and common::canBeChanged('build', $build)) $menu .= $this->buildMenu('build', 'view', "{$params}&type=story&link=true", $build, $type, 'link', '', '', '', "data-app={$tab}", $this->lang->build->linkStory);
$menu .= $this->buildMenu('testtask', 'create', "product=$build->product&execution={$executionID}&build=$build->id", $build, $type, 'bullhorn', '', '', '', "data-app='{$tab}'");
if($tab == 'execution') $menu .= $this->buildMenu('execution', 'bug', "execution={$extraParams['executionID']}&productID={$extraParams['productID']}&orderBy=status&build=$build->id", $build, $type, '', '', '', '', $this->lang->execution->viewBug);
if($tab == 'project') $menu .= $this->buildMenu('build', 'view', "{$params}&type=generatedBug", $build, $type, 'bug', '', '', '', "data-app='project'", $this->lang->project->bug);
$menu .= $this->buildMenu('build', 'edit', $params, $build, $type);
$menu .= $this->buildMenu('build', 'delete', $params, $build, $type, 'trash', 'hiddenwin');
}
else
{
$canBeChanged = common::canBeChanged('build', $build);
if($build->deleted || !$canBeChanged) return '';
$menu .= $this->buildFlowMenu('build', $build, 'view', 'direct');
$editClickable = $this->buildMenu('build', 'edit', $params, $build, $type, '', '', '', '', '', '', false);
$deleteClickable = $this->buildMenu('build', 'delete', $params, $build, $type, '', '', '', '', '', '', false);
if(common::hasPriv('build', 'edit') and $editClickable) $menu .= html::a(helper::createLink('build', 'edit', $params), "<i class='icon-common-edit icon-edit'></i> " . $this->lang->edit, '', "class='btn btn-link' title='{$this->lang->build->edit}' data-app='{$app->tab}'");
if(common::hasPriv('build', 'delete') and $deleteClickable) $menu .= html::a(helper::createLink('build', 'delete', $params), "<i class='icon-common-delete icon-trash'></i> " . $this->lang->delete, '', "class='btn btn-link' title='{$this->lang->build->delete}' target='hiddenwin' data-app='{$app->tab}'");
}
return $menu;
}
+4 -2
View File
@@ -92,7 +92,8 @@ class caselib extends control
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($libID);
$message = $this->executeHooks($libID);
if($message) $response['message'] = $message;
$response['locate'] = inlink('view', "libID=$libID");
return $this->send($response);
@@ -130,7 +131,8 @@ class caselib extends control
{
$this->caselib->delete($libID);
$this->executeHooks($libID);
$message = $this->executeHooks($libID);
if($message) $response['message'] = $message;
/* if ajax request, send result. */
if($this->server->ajax)
+4 -1
View File
@@ -647,10 +647,13 @@ class caselibModel extends model
$menu .= $this->buildMenu('testcase', 'review', $params, $case, 'browse', 'glasses', '', 'iframe');
}
$menu .= $this->buildMenu('testcase', 'edit', $params, $case, 'browse');
$clickable = $this->buildMenu('testcase', 'delete', $params, $case, 'browse', '', '', '', '', '', '', false);
if(common::hasPriv('testcase', 'delete'))
{
$deleteURL = helper::createLink('testcase', 'delete', "$params&confirm=yes");
$menu .= html::a("javascript:ajaxDelete(\"$deleteURL\", \"caseList\", confirmDelete)", '<i class="icon icon-trash"></i>', '', "title='{$this->lang->testcase->delete}' class='btn'");
$class = 'btn';
if(!$clickable) $class .= ' disabled';
$menu .= html::a("javascript:ajaxDelete(\"$deleteURL\", \"caseList\", confirmDelete)", '<i class="icon icon-trash"></i>', '', "title='{$this->lang->testcase->delete}' class='{$class}'");
}
return $menu;
+21 -2
View File
@@ -918,6 +918,9 @@ class commonModel extends model
public static function getMainNavList($moduleName)
{
global $lang;
global $app;
$app->loadLang('my');
$menuOrder = $lang->mainNav->menuOrder;
ksort($menuOrder);
@@ -963,8 +966,24 @@ class commonModel extends model
}
}
/* Check whether other preference item under the module have permissions. If yes, point to other methods. */
$moduleLinkList = $currentModule . 'LinkList';
if(!$display and isset($lang->my->$moduleLinkList))
{
foreach($lang->my->$moduleLinkList as $key => $linkList)
{
$method = explode('-', $key)[1];
if(common::hasPriv($currentModule, $method))
{
$display = true;
$currentMethod = $method;
break;
}
}
}
/* Check whether other methods under the module have permissions. If yes, point to other methods. */
if($display == false and isset($lang->$currentModule->menu))
if($display == false and isset($lang->$currentModule->menu) and !in_array($currentModule, array('program', 'product', 'project', 'execution')))
{
foreach($lang->$currentModule->menu as $menu)
{
@@ -1529,7 +1548,7 @@ class commonModel extends model
<h4 class="modal-title">{$lang->action->create}</h4>
</div>
<div class="modal-body">
<form class="load-indicator" action="{$commentFormLink}" target='hiddenwin' method='post'>
<form class="load-indicator not-watch" action="{$commentFormLink}" target='hiddenwin' method='post'>
<div class="form-group">
<textarea id='comment' name='comment' class="form-control" rows="8" autofocus="autofocus"></textarea>
</div>
+3
View File
@@ -245,7 +245,9 @@ class customModel extends model
$link = explode('|', $link);
list($label, $module, $method) = $link;
$hasPriv = commonModel::hasPriv($module, $method);
/* Fix bug #20464 */
if(isset($vars)) unset($vars);
if(!$hasPriv and is_array($item) and isset($item['subMenu']))
{
foreach($item['subMenu'] as $subMenu)
@@ -261,6 +263,7 @@ class customModel extends model
if($module == 'execution' and $method == 'more') $hasPriv = true;
if($module == 'project' and $method == 'other') $hasPriv = true;
if(!$hasPriv and isset($vars)) unset($vars);
}
if($isTutorialMode || $hasPriv)
+13 -12
View File
@@ -154,7 +154,11 @@ class doc extends control
$executions = $this->execution->getList();
/* Splice project name. */
foreach($executions as $executionID => $execution) $executions[$executionID] = $projects[$execution->project] . '/' . $execution->name;
foreach($executions as $executionID => $execution)
{
$executionPrefix = isset($projects[$execution->project]) ? $projects[$execution->project] . '/' : '';
$executions[$executionID] = $executionPrefix . $execution->name;
}
/* Get the project that has permission to view. */
foreach($projects as $projectID => $project) if(!$this->app->user->admin and strpos(',' . $this->app->user->view->projects . ',', ',' . $projectID . ',') === false) unset($projects[$projectID]);
@@ -246,17 +250,18 @@ class doc extends control
*
* @param int $libID
* @param string $confirm yes|no
* @param string $from lib|book
* @param string $type lib|book
* @param string $from tableContents|objectLibs
* @access public
* @return void
*/
public function deleteLib($libID, $confirm = 'no', $from = 'lib')
public function deleteLib($libID, $confirm = 'no', $type = 'lib', $from = 'objectLibs')
{
if($libID == 'product' or $libID == 'execution') return;
if($confirm == 'no')
{
$deleteTip = $from == 'book' ? $this->lang->doc->confirmDeleteBook : $this->lang->doc->confirmDeleteLib;
return print(js::confirm($deleteTip, $this->createLink('doc', 'deleteLib', "libID=$libID&confirm=yes")));
$deleteTip = $type == 'book' ? $this->lang->doc->confirmDeleteBook : $this->lang->doc->confirmDeleteLib;
return print(js::confirm($deleteTip, $this->createLink('doc', 'deleteLib', "libID=$libID&confirm=yes&type=$lib&from=$from")));
}
else
{
@@ -270,13 +275,9 @@ class doc extends control
return print(js::locate($this->createLink('doc', 'objectLibs', 'type=book'), 'parent.parent'));
}
$browseLink = $this->createLink('doc', 'index');
if(in_array($this->app->tab, array('product', 'project', 'execution')))
{
$objectType = $lib->type;
$objectID = $lib->{$objectType};
$browseLink = $this->createLink('doc', 'objectLibs', "type=$objectType&objectID=$objectID");
}
$objectType = $lib->type;
$objectID = strpos(',product,project,execution,', ",$objectType,") !== false ? $lib->{$objectType} : 0;
$browseLink = $this->createLink('doc', $from, "type=$objectType&objectID=$objectID");
return print(js::locate($browseLink, 'parent'));
}
+1 -1
View File
@@ -48,7 +48,7 @@ if(empty($type)) $type = 'product';
echo "<li class='divider'></li>";
}
if($canEditLib) echo '<li>' . html::a($this->createLink('doc', 'editLib', "rootID=$libID"), '<i class="icon-edit"></i> ' . $lang->doc->editLib, '', "class='iframe'") . '</li>';
if($canDeleteLib) echo '<li>' . html::a($this->createLink('doc', 'deleteLib', "rootID=$libID"), '<i class="icon-trash"></i> ' . $lang->doc->deleteLib, 'hiddenwin') . '</li>';
if($canDeleteLib) echo '<li>' . html::a($this->createLink('doc', 'deleteLib', "rootID=$libID&confirm=no&type=lib&from=tableContents"), '<i class="icon-trash"></i> ' . $lang->doc->deleteLib, 'hiddenwin') . '</li>';
echo '</ul></div>';
}
+1 -1
View File
@@ -7,7 +7,7 @@ $config->execution->weekend = '2';
$config->execution->ownerFields = array('PO', 'PM', 'QD', 'RD');
$config->execution->list = new stdclass();
$config->execution->list->exportFields = 'id,name,projectName,code,PM,end,status,totalEstimate,totalConsumed,totalLeft,progress';
$config->execution->list->exportFields = 'id,name,projectName,code,PM,begin,end,status,totalEstimate,totalConsumed,totalLeft,progress';
$config->execution->modelList['scrum'] = 'sprint';
$config->execution->modelList['waterfall'] = 'stage';
+9 -4
View File
@@ -679,7 +679,7 @@ class execution extends control
* @access public
* @return void
*/
public function story($executionID = 0, $orderBy = 'order_asc', $type = 'all', $param = 0, $recTotal = 0, $recPerPage = 50, $pageID = 1)
public function story($executionID = 0, $orderBy = 'order_desc', $type = 'all', $param = 0, $recTotal = 0, $recPerPage = 50, $pageID = 1)
{
/* Load these models. */
$this->loadModel('story');
@@ -1419,7 +1419,8 @@ class execution extends control
$this->loadModel('action')->create($this->objectType, $executionID, 'opened', '', join(',', $_POST['products']));
$this->executeHooks($executionID);
$message = $this->executeHooks($executionID);
if($message) $this->lang->saveSuccess = $message;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $executionID));
@@ -1593,7 +1594,9 @@ class execution extends control
$this->productplan->linkProject($projectID, $newPlans);
}
$this->executeHooks($executionID);
$message = $this->executeHooks($executionID);
if($message) $this->lang->saveSuccess = $message;
if($_POST['status'] == 'doing') $this->loadModel('common')->syncPPEStatus($executionID);
if($execution->type == 'kanban') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('view', "executionID=$executionID")));
@@ -2593,7 +2596,8 @@ class execution extends control
$this->execution->updateUserView($executionID);
$this->session->set('execution', '');
$this->executeHooks($executionID);
$message = $this->executeHooks($executionID);
if($message) $this->lang->saveSuccess = $message;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess));
return print(js::reload('parent'));
@@ -3291,6 +3295,7 @@ class execution extends control
$orderBy = $this->post->orderBy;
$order = $this->dao->select('*')->from(TABLE_PROJECTSTORY)->where('story')->in($idList)->andWhere('project')->eq($executionID)->orderBy('order_asc')->fetch('order');
if(strpos($orderBy, 'order_desc') !== false) $idList = array_reverse($idList);
foreach($idList as $storyID)
{
$this->dao->update(TABLE_PROJECTSTORY)->set('`order`')->eq($order)->where('story')->eq($storyID)->andWhere('project')->eq($executionID)->exec();
+2 -1
View File
@@ -1,4 +1,5 @@
#tipsModal {margin-top: 10%;}
[lang^='en'] #tipsModal {margin-top: 10%; max-width: 620px;}
[lang^='zh-cn'] #tipsModal {margin-top: 10%; max-width: 530px;}
.chosen-container-single .chosen-single > span {max-width: 100%;}
#copyProjectModal {padding: 0;}
+1 -1
View File
@@ -184,7 +184,7 @@ function loadPlans(product, branchID)
var branchID = typeof(branchID) == 'undefined' ? 0 : branchID;
var index = $(product).attr('id').replace('products', '');
$.get(createLink('product', 'ajaxGetPlans', "productID=" + productID + '&branch=0,' + branchID + '&planID=0&fieldID&needCreate=&expired=noclosed|' + (config.currentMethod == 'create' ? 'unexpired' : '') + '&param=skipParent'), function(data)
$.get(createLink('product', 'ajaxGetPlans', "productID=" + productID + '&branch=0,' + branchID + '&planID=0&fieldID&needCreate=&expired=noclosed,' + (config.currentMethod == 'create' ? 'unexpired' : '') + '&param=skipParent'), function(data)
{
if(data)
{
+2 -3
View File
@@ -233,15 +233,14 @@ $('.c-group').change(function()
*/
function createLaneMenu(options)
{
var lane = options.$trigger.closest('.kanban-lane').data('lane');
var laneCount = options.$trigger.closest('.kanban-board').children('.kanban-lane').length;
var lane = options.$trigger.closest('.kanban-lane').data('lane');
var privs = lane.actions;
if(!privs.length) return [];
var items = [];
if(privs.includes('setLane')) items.push({label: kanbanLang.setLane, icon: 'edit', url: createLink('kanban', 'setLane', 'laneID=' + lane.id + '&executionID=0&from=kanban'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '635px'}});
if(privs.includes('deleteLane') && laneCount > 1) items.push({label: kanbanLang.deleteLane, icon: 'trash', url: createLink('kanban', 'deleteLane', 'lane=' + lane.id), attrs: {'target': 'hiddenwin'}});
if(privs.includes('deleteLane')) items.push({label: kanbanLang.deleteLane, icon: 'trash', url: createLink('kanban', 'deleteLane', 'lane=' + lane.id), attrs: {'target': 'hiddenwin'}});
var bounds = options.$trigger[0].getBoundingClientRect();
items.$options = {x: bounds.right, y: bounds.top};
+1 -1
View File
@@ -9,7 +9,7 @@ $(function()
var $target = $(data.element[0]);
$target.hide();
$target.fadeIn(1000);
order = 'order_asc'
order = 'order_desc'
history.pushState({}, 0, createLink('execution', 'story', "executionID=" + executionID + '&orderBy=' + order));
});
});
+21
View File
@@ -17,9 +17,29 @@ $lang->execution->type = $lang->executionCommon . 'Type';
$lang->execution->name = "{$lang->executionCommon} Name";
$lang->execution->code = "{$lang->executionCommon} Code";
$lang->execution->projectName = 'Project';
$lang->execution->project = 'Project';
$lang->execution->execName = "{$lang->execution->common} Name";
$lang->execution->execCode = "{$lang->execution->common} Code";
$lang->execution->execType = 'Execution Type';
$lang->execution->lifetime = 'Project Cycle';
$lang->execution->attribute = 'Stage Type';
$lang->execution->percent = 'Workload %';
$lang->execution->milestone = 'Milestone';
$lang->execution->parent = 'Project';
$lang->execution->path = 'Path';
$lang->execution->grade = 'Grade';
$lang->execution->output = 'Output';
$lang->execution->version = 'Version';
$lang->execution->parentVersion = 'Parent Version';
$lang->execution->planDuration = 'Plan Duration';
$lang->execution->realDuration = 'Real Duration';
$lang->execution->openedVersion = 'Opened Version';
$lang->execution->lastEditedBy = 'Last EditedBy';
$lang->execution->lastEditedDate = 'Last EditedDate';
$lang->execution->suspendedDate = 'Suspended Date';
$lang->execution->vision = 'Vision';
$lang->execution->displayCards = 'Max cards per column';
$lang->execution->fluidBoard = 'Column Width';
$lang->execution->stage = 'Stage';
$lang->execution->pri = 'Priority';
$lang->execution->openedBy = 'OpenedBy';
@@ -55,6 +75,7 @@ $lang->execution->QD = 'Test Manager';
$lang->execution->RD = 'Release Manager';
$lang->execution->release = 'Release';
$lang->execution->acl = 'Access Control';
$lang->execution->auth = 'Privileges';
$lang->execution->teamname = 'Team Name';
$lang->execution->updateOrder = 'Rank';
$lang->execution->order = "Rank {$lang->executionCommon}";
+21
View File
@@ -17,9 +17,29 @@ $lang->execution->type = $lang->executionCommon . '类型';
$lang->execution->name = $lang->executionCommon . '名称';
$lang->execution->code = $lang->executionCommon . '代号';
$lang->execution->projectName = '所属项目';
$lang->execution->project = '所属项目';
$lang->execution->execName = "{$lang->execution->common}名称";
$lang->execution->execCode = "{$lang->execution->common}代号";
$lang->execution->execType = "{$lang->execution->common}类型";
$lang->execution->lifetime = '项目周期';
$lang->execution->attribute = '阶段类型';
$lang->execution->percent = '工作量占比';
$lang->execution->milestone = '里程碑';
$lang->execution->parent = '所属项目';
$lang->execution->path = '路径';
$lang->execution->grade = '层级';
$lang->execution->output = '输出';
$lang->execution->version = '版本';
$lang->execution->parentVersion = '父版本';
$lang->execution->planDuration = '计划周期天数';
$lang->execution->realDuration = '实际周期天数';
$lang->execution->openedVersion = '创建版本';
$lang->execution->lastEditedBy = '最后编辑人';
$lang->execution->lastEditedDate = '最后编辑日期';
$lang->execution->suspendedDate = '暂停日期';
$lang->execution->vision = '界面';
$lang->execution->displayCards = '每列最大卡片数';
$lang->execution->fluidBoard = '列宽度';
$lang->execution->stage = '阶段';
$lang->execution->pri = '优先级';
$lang->execution->openedBy = '由谁创建';
@@ -55,6 +75,7 @@ $lang->execution->QD = '测试负责人';
$lang->execution->RD = '发布负责人';
$lang->execution->release = '发布';
$lang->execution->acl = '访问控制';
$lang->execution->auth = '权限控制';
$lang->execution->teamname = '团队名称';
$lang->execution->updateOrder = '排序';
$lang->execution->order = $lang->executionCommon . '排序';
+33 -7
View File
@@ -369,12 +369,12 @@ class executionModel extends model
$this->lang->project->code = $this->lang->execution->execCode;
}
$sprintProject = isset($sprint->project) ? $sprint->project : '';
$sprintProject = isset($sprint->project) ? $sprint->project : '0';
$this->dao->insert(TABLE_EXECUTION)->data($sprint)
->autoCheck($skipFields = 'begin,end')
->batchcheck($this->config->execution->create->requiredFields, 'notempty')
->checkIF((!empty($sprint->name) and $this->config->systemMode == 'new'), 'name', 'unique', "`type` in ('sprint','stage', 'kanban') and `project` = $sprintProject")
->checkIF(!empty($sprint->code), 'code', 'unique', "`type` in ('sprint','stage')")
->checkIF(!empty($sprint->code), 'code', 'unique', "`type` in ('sprint','stage', 'kanban')")
->checkIF($sprint->begin != '', 'begin', 'date')
->checkIF($sprint->end != '', 'end', 'date')
->checkIF($sprint->end != '', 'end', 'ge', $sprint->begin)
@@ -511,18 +511,17 @@ class executionModel extends model
}
/* Update data. */
$executionProject = isset($execution->project) ? $execution->project : '';
$executionProject = isset($execution->project) ? $execution->project : '0';
$this->dao->update(TABLE_EXECUTION)->data($execution)
->autoCheck($skipFields = 'begin,end')
->batchcheck($this->config->execution->edit->requiredFields, 'notempty')
->checkIF($execution->begin != '', 'begin', 'date')
->checkIF($execution->end != '', 'end', 'date')
->checkIF($execution->end != '', 'end', 'ge', $execution->begin)
->checkIF((!empty($execution->name) and $this->config->systemMode == 'new'), 'name', 'unique', "id != $executionID and type in ('sprint','stage') and `project` = $executionProject")
->checkIF(!empty($execution->code), 'code', 'unique', "id != $executionID and type in ('sprint','stage')")
->checkIF((!empty($execution->name) and $this->config->systemMode == 'new'), 'name', 'unique', "id != $executionID and type in ('sprint','stage', 'kanban') and `project` = $executionProject")
->checkIF(!empty($execution->code), 'code', 'unique', "id != $executionID and type in ('sprint','stage', 'kanban')")
->checkFlow()
->where('id')->eq($executionID)
->checkFlow()
->limit(1)
->exec();
@@ -961,6 +960,16 @@ class executionModel extends model
}
}
/* Update the status of the parent stage. */
if($oldExecution->type == 'stage')
{
$parent = $this->getByID($oldExecution->parent);
if($parent->type == 'stage' and $parent->status == 'closed')
{
$this->dao->update(TABLE_EXECUTION)->set('status')->eq('doing')->where('id')->eq($parent->id)->exec();
}
}
if(!dao::isError()) return common::createChanges($oldExecution, $execution);
}
@@ -1002,6 +1011,23 @@ class executionModel extends model
if(!dao::isError())
{
/* Update the status of the parent stage. */
if($oldExecution->type == 'stage')
{
$parent = $this->getByID($oldExecution->parent);
if($parent->type == 'stage')
{
$isClosed = true;
$children = $this->getChildExecutions($oldExecution->parent);
foreach($children as $childID => $childExecution)
{
if($childExecution->status != 'closed') $isClosed = false;
}
if($isClosed) $this->dao->update(TABLE_EXECUTION)->set('status')->eq('closed')->where('id')->eq($parent->id)->exec();
}
}
$this->loadModel('score')->create('execution', 'close', $oldExecution);
return common::createChanges($oldExecution, $execution);
}
@@ -1575,7 +1601,7 @@ class executionModel extends model
*/
public function getChildExecutions($executionID)
{
return $this->dao->select('id, name')->from(TABLE_EXECUTION)->where('parent')->eq((int)$executionID)->fetchPairs();
return $this->dao->select('id, name, status')->from(TABLE_EXECUTION)->where('deleted')->eq(0)->andWhere('parent')->eq((int)$executionID)->fetchAll('id');
}
/**
+23 -5
View File
@@ -185,12 +185,21 @@
echo common::hasPriv('programplan', 'create') ? html::a('javascript:alert("' . $this->lang->programplan->error->createdTask . '");', '<i class="icon-programplan-create icon-split"></i>', '', 'class="btn ' . $disabled . '"') : '';
}
common::printIcon('programplan', 'edit', "planID=$execution->id&projectID=$projectID", $execution, 'list', '', '', 'iframe', true);
common::printIcon('programplan', 'edit', "stageID=$execution->id&projectID=$projectID", $execution, 'list', '', '', 'iframe', true);
$disabled = !empty($execution->children) ? ' disabled' : '';
if($execution->status != 'closed' and common::hasPriv('execution', 'close', $execution))
{
common::printIcon('execution', 'close', "stageID=$execution->id", $execution, 'list', 'off', 'hiddenwin' , $disabled . ' iframe', true, '', $this->lang->programplan->close);
}
elseif($execution->status == 'closed' and common::hasPriv('execution', 'activate', $execution))
{
common::printIcon('execution', 'activate', "stageID=$execution->id", $execution, 'list', 'magic', 'hiddenwin' , $disabled . ' iframe', true, '', $this->lang->programplan->activate);
}
if(common::hasPriv('execution', 'delete', $execution))
{
common::printIcon('execution', 'delete', "planID=$execution->id&confirm=no", $execution, 'list', 'trash', 'hiddenwin' , $disabled, '', '', $this->lang->programplan->delete);
common::printIcon('execution', 'delete', "stageID=$execution->id&confirm=no", $execution, 'list', 'trash', 'hiddenwin' , $disabled, '', '', $this->lang->programplan->delete);
}
?></td>
<?php else:?>
@@ -257,7 +266,7 @@
if($child->grade == 1 && $this->loadModel('programplan')->isCreateTask($child->id))
{
common::printIcon('programplan', 'create', "program={$child->parent}&productID=$productID&planID=$child->id", $child, 'list', 'split', '', '', '', '', $this->lang->programplan->createSubPlan);
common::printIcon('programplan', 'create', "program={$child->parent}&productID=$productID&stageID=$child->id", $child, 'list', 'split', '', '', '', '', $this->lang->programplan->createSubPlan);
}
else
{
@@ -265,12 +274,21 @@
echo html::a('javascript:alert("' . $this->lang->programplan->error->createdTask . '");', '<i class="icon-programplan-create icon-split"></i>', '', 'class="btn ' . $disabled . '"');
}
common::printIcon('programplan', 'edit', "planID=$child->id&projectID=$projectID", $child, 'list', '', '', 'iframe', true);
common::printIcon('programplan', 'edit', "stageID=$child->id&projectID=$projectID", $child, 'list', '', '', 'iframe', true);
$disabled = !empty($child->children) ? ' disabled' : '';
if(common::hasPriv('execution', 'close', $child) and $execution->status != 'closed')
{
common::printIcon('execution', 'close', "stageID=$child->id", $child, 'list', 'off', '' , $disabled . ' iframe', true, '', $this->lang->programplan->close);
}
elseif(common::hasPriv('execution', 'activate', $child) and $execution->status == 'closed')
{
common::printIcon('execution', 'activate', "stageID=$child->id", $child, 'list', 'magic', 'hiddenwin' , $disabled . ' iframe', true, '', $this->lang->programplan->activate);
}
if(common::hasPriv('execution', 'delete', $child))
{
common::printIcon('execution', 'delete', "planID=$child->id&confirm=no", $child, 'list', 'trash', 'hiddenwin' , $disabled, '', '', $this->lang->programplan->delete);
common::printIcon('execution', 'delete', "stageID=$child->id&confirm=no", $child, 'list', 'trash', 'hiddenwin' , $disabled, '', '', $this->lang->programplan->delete);
}
?>
</td>
+1 -13
View File
@@ -72,19 +72,7 @@
<td class="c-url" title="<?php echo $build->filePath?>"><?php echo strpos($build->filePath, 'http') === 0 ? html::a($build->filePath) : $build->filePath;?></td>
<td class="c-date"><?php echo $build->date?></td>
<td class="c-user em"><?php echo zget($users, $build->builder);?></td>
<td class="c-actions">
<?php
if(common::hasPriv('build', 'linkstory') and common::hasPriv('build', 'view') and common::canBeChanged('build', $build))
{
echo html::a($this->createLink('build', 'view', "buildID=$build->id&type=story&link=true"), "<i class='icon icon-link'></i>", '', "class='btn' title='{$lang->build->linkStory}'");
}
common::printIcon('testtask', 'create', "product=$build->product&execution=$execution->id&build=$build->id", $build, 'list', 'bullhorn');
$lang->execution->bug = $lang->execution->viewBug;
common::printIcon('execution', 'bug', "execution=$execution->id&productID=$productID&orderBy=status&build=$build->id", $build, 'list');
common::printIcon('build', 'edit', "buildID=$build->id", $build, 'list');
common::printIcon('build', 'delete', "buildID=$build->id", $build, 'list', 'trash', 'hiddenwin');
?>
</td>
<td class="c-actions"><?php echo $this->build->buildOperateMenu($build, 'browse', "executionID={$execution->id}&productID={$productID}");?></td>
</tr>
<?php endforeach;?>
<?php endforeach;?>
+1 -1
View File
@@ -15,7 +15,7 @@
<?php $defaultURL = $this->createLink('execution', 'task', "execution=$executionID");?>
<?php include '../../common/view/header.html.php';?>
<body>
<div class='modal-dialog mw-700px' id='tipsModal'>
<div class='modal-dialog' id='tipsModal'>
<div class='modal-header'>
<a href='<?php echo $defaultURL;?>' class='close'><i class="icon icon-close"></i></a>
<h4 class='modal-title' id='myModalLabel'><?php echo $lang->execution->tips;?></h4>
+2 -2
View File
@@ -46,8 +46,8 @@
<?php
if(common::hasPriv('execution', 'story'))
{
echo html::a($this->createLink('execution', 'story', "executionID=$execution->id&orderBy=order_asc&type=all"), "<span class='text'>{$lang->story->allStories}</span>" . ($type == 'all' ? " <span class='label label-light label-badge'>{$pager->recTotal}</span>" : ''), '', "class='btn btn-link" . ($type == 'all' ? " btn-active-text" : '') . "'");
echo html::a($this->createLink('execution', 'story', "executionID=$execution->id&orderBy=order_asc&type=unclosed"), "<span class='text'>{$lang->story->unclosed}</span>" . ($type == 'unclosed' ? " <span class='label label-light label-badge'>{$pager->recTotal}</span>" : ''), '', "class='btn btn-link" . ($type == 'unclosed' ? " btn-active-text" : '') . "'");
echo html::a($this->createLink('execution', 'story', "executionID=$execution->id&orderBy=order_desc&type=all"), "<span class='text'>{$lang->story->allStories}</span>" . ($type == 'all' ? " <span class='label label-light label-badge'>{$pager->recTotal}</span>" : ''), '', "class='btn btn-link" . ($type == 'all' ? " btn-active-text" : '') . "'");
echo html::a($this->createLink('execution', 'story', "executionID=$execution->id&orderBy=order_desc&type=unclosed"), "<span class='text'>{$lang->story->unclosed}</span>" . ($type == 'unclosed' ? " <span class='label label-light label-badge'>{$pager->recTotal}</span>" : ''), '', "class='btn btn-link" . ($type == 'unclosed' ? " btn-active-text" : '') . "'");
}
if(common::hasPriv('execution', 'storykanban')) echo html::a($this->createLink('execution', 'storykanban', "executionID=$execution->id"), "<span class='text'>{$lang->execution->kanban}</span>", '', "class='btn btn-link'");
?>
+1 -1
View File
@@ -1,4 +1,4 @@
<div style='margin: 0 auto; max-width: 580px'>
<div style='margin: 0 auto; max-width: <?php echo $this->app->getClientLang() == 'zh-cn' ? '500px' : '580px';?>'>
<p><strong><?php echo $lang->execution->afterInfo;?></strong></p>
<div>
<?php echo html::a($this->createLink('execution', 'team', "executionID=$executionID"), $lang->execution->setTeam, '', "class='btn' data-app='execution'");?>
+1
View File
@@ -257,6 +257,7 @@ if($isCustomExport)
{
$field = trim($field);
$exportFieldPairs[$field] = isset($moduleLang->$field) ? $moduleLang->$field : (isset($lang->$field) ? $lang->$field : $field);
if(!is_string($exportFieldPairs[$field])) $exportFieldPairs[$field] = $field;
if(!$hasDefaultField)$selectedFields[] = $field;
}
js::set('defaultExportFields', join(',', $selectedFields));
+4
View File
@@ -36,6 +36,10 @@
}
else
{
url = url.replace('?onlybody=yes&', '?');
url = url.replace('?onlybody=yes', '?');
url = url.replace('&onlybody=yes', '');
window.open(url, '_blank');
}
return false;
+1 -1
View File
@@ -22,7 +22,7 @@ $lang->group->managePrivByModule = 'Manage Privileges by Module';
$lang->group->byModuleTips = '<span class="tips">(Press Shift/Ctrl to Multi-select)</span>';
$lang->group->manageMember = 'Manage Members';
$lang->group->manageProjectAdmin = 'Manage Program Admins';
$lang->group->confirmDelete = 'Do you want to delete this user group?';
$lang->group->confirmDelete = "Do you want to delete '%s'?";
$lang->group->successSaved = 'Saved.';
$lang->group->errorNotSaved = 'Failed. Please select actions and groups.';
$lang->group->viewList = 'Access Sight';
+2
View File
@@ -624,6 +624,7 @@ $lang->resource->kanban->sortSpace = 'sortSpace';
$lang->resource->kanban->create = 'create';
$lang->resource->kanban->edit = 'edit';
$lang->resource->kanban->view = 'view';
$lang->resource->kanban->activate = 'activate';
$lang->resource->kanban->close = 'close';
$lang->resource->kanban->delete = 'delete';
$lang->resource->kanban->createRegion = 'createRegion';
@@ -712,6 +713,7 @@ $lang->kanban->methodorder[220] = 'setColumnWidth';
$lang->kanban->methodOrder[225] = 'batchCreateCard';
$lang->kanban->methodorder[230] = 'import';
$lang->kanban->methodorder[235] = 'enableArchived';
$lang->kanban->methodorder[240] = 'activate';
/* Execution. */
$lang->resource->execution = new stdclass();
+1 -1
View File
@@ -22,7 +22,7 @@ $lang->group->managePrivByModule = '按模块分配权限';
$lang->group->byModuleTips = '<span class="tips">(可以按住Shift或者Ctrl键进行多选)</span>';
$lang->group->manageMember = '成员维护';
$lang->group->manageProjectAdmin = '维护项目管理员';
$lang->group->confirmDelete = '您确定删除该用户分组吗?';
$lang->group->confirmDelete = '您确定删除“%s”用户分组吗?';
$lang->group->successSaved = '成功保存';
$lang->group->errorNotSaved = '没有保存,请确认选择了权限数据。';
$lang->group->viewList = '可访问视图';
+2 -1
View File
@@ -65,7 +65,8 @@
else
{
$deleteURL = $this->createLink('group', 'delete', "groupID=$group->id&confirm=yes");
echo html::a("javascript:ajaxDelete(\"$deleteURL\", \"groupList\", confirmDelete)", '<i class="icon icon-trash"></i>', '', "title='{$lang->group->delete}' class='btn'");
js::set("confirmDelete{$group->id}", sprintf($lang->group->confirmDelete, $group->name));
echo html::a("javascript:ajaxDelete(\"$deleteURL\", \"groupList\", confirmDelete{$group->id})", '<i class="icon icon-trash"></i>', '', "title='{$lang->group->delete}' class='btn'");
}
}
?>
+1
View File
@@ -41,6 +41,7 @@ $config->kanban->editor->editspace = array('id' => 'desc', 'tools' => 'simpl
$config->kanban->editor->closespace = array('id' => 'comment', 'tools' => 'simpleTools');
$config->kanban->editor->activatespace = array('id' => 'comment', 'tools' => 'simpleTools');
$config->kanban->editor->createcard = array('id' => 'desc', 'tools' => 'simpleTools');
$config->kanban->editor->activate = array('id' => 'comment', 'tools' => 'simpleTools');
$config->kanban->editor->close = array('id' => 'comment', 'tools' => 'simpleTools');
$config->kanban->editor->editcard = array('id' => 'desc', 'tools' => 'simpleTools');
$config->kanban->editor->viewcard = array('id' => 'comment', 'tools' => 'simpleTools');
+30
View File
@@ -269,6 +269,36 @@ class kanban extends control
$this->display();
}
/*
* Activate a kanban.
*
* @param int $kanbanID
* @access public
* @return void
*/
public function activate($kanbanID)
{
$this->loadModel('action');
if(!empty($_POST))
{
$changes = $this->kanban->activate($kanbanID);
if(dao::isError()) return print(js::error(dao::getError()));
$actionID = $this->action->create('kanban', $kanbanID, 'activated', $this->post->comment);
$this->action->logHistory($actionID, $changes);
return print(js::reload('parent.parent'));
}
$this->view->kanban = $this->kanban->getByID($kanbanID);
$this->view->actions = $this->action->getList('kanban', $kanbanID);
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->display();
}
/*
* Close a kanban.
*
+1
View File
@@ -9,6 +9,7 @@ $lang->kanban->deleteSpace = 'Delete Space';
$lang->kanban->sortSpace = 'Sort Space';
$lang->kanban->edit = 'Edit Kanban';
$lang->kanban->view = 'View Kanban';
$lang->kanban->activate = 'Activate Kanban';
$lang->kanban->close = 'Close Kanban';
$lang->kanban->delete = 'Delete Kanban';
$lang->kanban->createRegion = 'Create Region';
+1
View File
@@ -9,6 +9,7 @@ $lang->kanban->activateSpace = '激活空间';
$lang->kanban->sortSpace = '空间排序';
$lang->kanban->edit = '设置看板';
$lang->kanban->view = '查看看板';
$lang->kanban->activate = '激活看板';
$lang->kanban->close = '关闭看板';
$lang->kanban->delete = '删除看板';
$lang->kanban->createRegion = '新增区域';
+37 -3
View File
@@ -2086,6 +2086,37 @@ class kanbanModel extends model
}
}
/**
* Activate a kanban.
*
* @param int $kanbanID
* @access public
* @return array
*/
function activate($kanbanID)
{
$kanbanID = (int)$kanbanID;
$oldKanban = $this->getByID($kanbanID);
$now = helper::now();
$kanban = fixer::input('post')
->setDefault('status', 'active')
->setDefault('activatedBy', $this->app->user->account)
->setDefault('activatedDate', $now)
->setDefault('closedBy', '')
->setDefault('closedDate', '0000-00-00 00:00:00')
->setDefault('lastEditedBy', $this->app->user->account)
->setDefault('lastEditedDate', $now)
->remove('comment')
->get();
$this->dao->update(TABLE_KANBAN)->data($kanban)
->autoCheck()
->where('id')->eq($kanbanID)
->exec();
if(!dao::isError()) return common::createChanges($oldKanban, $kanban);
}
/**
* Close a kanban.
*
@@ -2102,6 +2133,8 @@ class kanbanModel extends model
->setDefault('status', 'closed')
->setDefault('closedBy', $this->app->user->account)
->setDefault('closedDate', $now)
->setDefault('activatedBy', '')
->setDefault('activatedDate', '0000-00-00 00:00:00')
->setDefault('lastEditedBy', $this->app->user->account)
->setDefault('lastEditedDate', $now)
->remove('comment')
@@ -2983,7 +3016,7 @@ class kanbanModel extends model
$CRKanban = !(isset($this->config->CRKanban) and $this->config->CRKanban == '0' and $kanban->status == 'closed');
$printRegionBtn = ($CRKanban and (common::hasPriv('kanban', 'createRegion') or $printSetHeightBtn or common::hasPriv('kanban', 'performable') or common::hasPriv('kanban', 'enableArchived') or common::hasPriv('kanban', 'import') or common::hasPriv('kanban', 'setColumnWidth')));
$printKanbanBtn = (common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete'));
$printKanbanBtn = (common::hasPriv('kanban', 'edit') or ($kanban->status == 'active' and common::hasPriv('kanban', 'close')) or common::hasPriv('kanban', 'delete') or ($kanban->status == 'closed' and common::hasPriv('kanban', 'activate')));
if($printRegionBtn or $printKanbanBtn)
{
@@ -3003,9 +3036,9 @@ class kanbanModel extends model
if(common::hasPriv('kanban', 'performable') and $CRKanban) $actions .= '<li>' . html::a(helper::createLink('kanban', 'performable', "kanbanID=$kanban->id", '', true), '<i class="icon icon-checked"></i>' . $this->lang->kanban->manageProgress, '', "class='iframe btn btn-link' data-width=40%") . '</li>';
$kanbanActions = '';
$attr = $kanban->status == 'closed' ? "disabled='disabled'" : '';
if(common::hasPriv('kanban', 'edit')) $kanbanActions .= '<li>' . html::a(helper::createLink('kanban', 'edit', "kanbanID=$kanban->id", '', true), '<i class="icon icon-edit"></i>' . $this->lang->kanban->edit, '', "class='iframe btn btn-link' data-width='75%'") . '</li>';
if(common::hasPriv('kanban', 'close')) $kanbanActions .= '<li>' . html::a(helper::createLink('kanban', 'close', "kanbanID=$kanban->id", '', true), '<i class="icon icon-off"></i>' . $this->lang->kanban->close, '', "class='iframe btn btn-link' $attr") . '</li>';
if(common::hasPriv('kanban', 'close') and $kanban->status == 'active') $kanbanActions .= '<li>' . html::a(helper::createLink('kanban', 'close', "kanbanID=$kanban->id", '', true), '<i class="icon icon-off"></i>' . $this->lang->kanban->close, '', "class='iframe btn btn-link'") . '</li>';
if(common::hasPriv('kanban', 'activate') and $kanban->status == 'closed') $kanbanActions .= '<li>' . html::a(helper::createLink('kanban', 'activate', "kanbanID=$kanban->id", '', true), '<i class="icon icon-magic"></i>' . $this->lang->kanban->activate, '', "class='iframe btn btn-link'") . '</li>';
if(common::hasPriv('kanban', 'delete')) $kanbanActions .= '<li>' . html::a(helper::createLink('kanban', 'delete', "kanbanID=$kanban->id"), '<i class="icon icon-trash"></i>' . $this->lang->kanban->delete, 'hiddenwin', "class='btn btn-link'") . '</li>';
if($kanbanActions)
{
@@ -3670,6 +3703,7 @@ class kanbanModel extends model
$count = $this->dao->select('COUNT(id) AS count')->from(TABLE_KANBANLANE)
->where('deleted')->eq('0')
->andWhere('region')->eq($object->region)
->beginIF($action == 'deletelane')->andWhere('type')->eq($object->type)->fi()
->beginIF($action == 'sortlane')->andWhere('`group`')->eq($object->group)->fi()
->fetch('count');
return $count > 1;
+40
View File
@@ -0,0 +1,40 @@
<?php
/**
* The activate file of kanban module of ZenTaoPMS.
*
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Mengyi Liu <liumengyi@easycorp.ltd>
* @package kanban
* @version $Id: activate.html.php 935 2022-05-25 13:18:24Z $
* @link https://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2>
<span class='label label-id'><?php echo $kanban->id;?></span>
<?php echo "<span title='$kanban->name'>" . $kanban->name . '</span>';?>
</h2>
</div>
<form method='post' enctype='multipart/form-data' target='hiddenwin'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->comment;?></th>
<td colspan='2'><?php echo html::textarea('comment', '', "rows='6'");?></td>
</tr>
<tr>
<td colspan='3' class='text-center form-actions'>
<?php echo html::submitButton($lang->kanban->activate);?>
</td>
</tr>
</table>
</form>
<hr class='small' />
<div class='main'><?php include '../../common/view/action.html.php';?></div>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+18 -8
View File
@@ -72,27 +72,37 @@
<?php endif;?>
<strong title='<?php echo $kanban->name;?>'><?php echo $kanban->name;?></strong>
</div>
<?php $canActions = (common::hasPriv('kanban','edit') or common::hasPriv('kanban','close') or common::hasPriv('kanban','delete'));?>
<?php if($canActions):?>
<?php
$canEdit = common::hasPriv('kanban','edit');
$canDelete = common::hasPriv('kanban','delete');
$canClose = (common::hasPriv('kanban', 'close') and $kanban->status == 'active');
$canActivate = (common::hasPriv('kanban', 'activate') and $kanban->status == 'closed');
?>
<?php if($canEdit or $canDelete or $canClose or $canActivate):?>
<div class='kanban-actions kanban-actions<?php echo $kanbanID;?>'>
<div class='dropdown'>
<?php echo html::a('javascript:;', "<i class='icon icon-ellipsis-v'></i>", '', "data-toggle='dropdown' class='btn btn-link'");?>
<ul class='dropdown-menu <?php echo $kanbanCount % 4 == 0 ? 'pull-left' : 'pull-right';?>'>
<?php
if(common::hasPriv('kanban','edit'))
if($canEdit)
{
echo '<li>';
common::printLink('kanban', 'edit', "kanbanID={$kanban->id}", '<i class="icon icon-edit"></i> ' . $lang->kanban->edit, '', "class='iframe' data-width='75%'", '', true);
echo '</li>';
}
if(common::hasPriv('kanban','close'))
if($canClose)
{
$class = $kanban->status == 'closed' ? 'disabled' : '';
echo "<li class='{$class}'>";
common::printLink('kanban', 'close', "kanbanID={$kanban->id}", '<i class="icon icon-off"></i> ' . $lang->kanban->close, '', "class='iframe {$class}' data-width='75%'", '', true);
echo "<li>";
common::printLink('kanban', 'close', "kanbanID={$kanban->id}", '<i class="icon icon-off"></i> ' . $lang->kanban->close, '', "class='iframe' data-width='75%'", '', true);
echo '</li>';
}
if(common::hasPriv('kanban','delete'))
if($canActivate)
{
echo "<li>";
common::printLink('kanban', 'activate', "kanbanID={$kanban->id}", '<i class="icon icon-magic"></i> ' . $lang->kanban->activate, '', "class='iframe' data-width='75%'", '', true);
echo '</li>';
}
if($canDelete)
{
echo '<li>';
common::printLink('kanban', 'delete', "kanbanID={$kanban->id}", '<i class="icon icon-trash"></i> ' . $lang->kanban->delete, 'hiddenwin');
+4 -1
View File
@@ -53,6 +53,7 @@ $app->loadLang('execution');
$app->loadLang('release');
$app->loadLang('build');
$app->loadLang('productplan');
js::set('systemMode', $this->config->systemMode);
?>
<div class='panel'>
<div class='panel-heading text-center'>
@@ -199,10 +200,12 @@ $(function()
var icon = '';
if($item.children('.build').length) icon = '<i class="icon icon-ver">';
if($item.children('.execution').length) icon = '<i class="icon icon-run">';
if($item.children('.productplan').length) icon = '<i class="icon icon-delay">';
if($item.children('.release').length) icon = '<i class="icon icon-publish">';
if($item.children('.execution').length && systemMode == 'new') icon = '<i class="icon icon-run">';
if($item.children('.execution').length && systemMode == 'classic') icon = '<i class="icon icon-project">';
$item.children('.cardName').prepend(icon);
});
})
+6 -3
View File
@@ -365,7 +365,8 @@ class product extends control
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->loadModel('action')->create('product', $productID, 'opened');
$this->executeHooks($productID);
$message = $this->executeHooks($productID);
if($message) $this->lang->saveSuccess = $message;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $productID));
$tab = $this->app->tab;
@@ -519,7 +520,8 @@ class product extends control
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($productID);
$message = $this->executeHooks($productID);
if($message) $this->lang->saveSuccess = $message;
$moduleName = $programID ? 'program' : 'product';
$methodName = $programID ? 'product' : 'view';
@@ -779,7 +781,8 @@ class product extends control
$this->product->delete(TABLE_PRODUCT, $productID);
$this->dao->update(TABLE_DOCLIB)->set('deleted')->eq(1)->where('product')->eq($productID)->exec();
$this->session->set('product', '');
$this->executeHooks($productID);
$message = $this->executeHooks($productID);
if($message) $this->lang->saveSuccess = $message;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess));
return print(js::locate($this->createLink('product', 'all'), 'parent'));
+1 -1
View File
@@ -646,7 +646,7 @@ class productModel extends model
->get();
$product = $this->loadModel('file')->processImgURL($product, $this->config->product->editor->create['id'], $this->post->uid);
$programID = isset($product->program) ? $product->program : '';
$programID = isset($product->program) ? $product->program : 0;
$this->dao->insert(TABLE_PRODUCT)->data($product)->autoCheck()
->batchCheck($this->config->product->create->requiredFields, 'notempty')
->checkIF((!empty($product->name) and $this->config->systemMode == 'new'), 'name', 'unique', "`program` = $programID")
+9 -5
View File
@@ -64,7 +64,8 @@ class productplan extends control
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->loadModel('action')->create('productplan', $planID, 'opened');
$this->executeHooks($planID);
$message = $this->executeHooks($planID);
if($message) $this->lang->saveSuccess = $message;
if($parent > 0) $this->productplan->updateParentStatus($parent);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
@@ -136,7 +137,8 @@ class productplan extends control
$actionID = $this->loadModel('action')->create('productplan', $planID, 'edited');
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($planID);
$message = $this->executeHooks($planID);
if($message) $this->lang->saveSuccess = $message;
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('view', "planID=$planID")));
}
@@ -252,7 +254,8 @@ class productplan extends control
{
$this->productplan->delete(TABLE_PRODUCTPLAN, $planID);
if($plan->parent > 0) $this->productplan->changeParentField($planID);
$this->executeHooks($planID);
$message = $this->executeHooks($planID);
if($message) $this->lang->saveSuccess = $message;
/* if ajax request, send result. */
if($this->server->ajax)
@@ -372,7 +375,7 @@ class productplan extends control
* @access public
* @return void
*/
public function view($planID = 0, $type = 'story', $orderBy = 'order_asc', $link = 'false', $param = '', $recTotal = 0, $recPerPage = 100, $pageID = 1)
public function view($planID = 0, $type = 'story', $orderBy = 'order_desc', $link = 'false', $param = '', $recTotal = 0, $recPerPage = 100, $pageID = 1)
{
$planID = (int)$planID;
$plan = $this->productplan->getByID($planID, true);
@@ -407,6 +410,7 @@ class productplan extends control
$planStories = $this->story->getPlanStories($planID, 'all', $type == 'story' ? $sort : 'id_desc', $storyPager);
$this->executeHooks($planID);
if($plan->parent > 0) $this->view->parentPlan = $this->productplan->getById($plan->parent);
if($plan->parent == '-1') $this->view->childrenPlans = $this->productplan->getChildren($plan->id);
@@ -606,7 +610,7 @@ class productplan extends control
* @access public
* @return void
*/
public function linkStory($planID = 0, $browseType = '', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 100, $pageID = 1)
public function linkStory($planID = 0, $browseType = '', $param = 0, $orderBy = 'order_desc', $recTotal = 0, $recPerPage = 100, $pageID = 1)
{
if(!empty($_POST['stories']))
{
+1 -1
View File
@@ -80,7 +80,7 @@ $(function()
var $target = $(data.element[0]);
$target.hide();
$target.fadeIn(1000);
order = 'order_asc';
order = 'order_desc';
history.pushState({}, 0, createLink('productplan', 'view', "planID=" + planID + '&type=story&orderBy=' + order));
});
});
-5
View File
@@ -142,11 +142,6 @@ $lang->productplan->featureBar['browse']['doing'] = 'Doing';
$lang->productplan->featureBar['browse']['done'] = 'Done';
$lang->productplan->featureBar['browse']['closed'] = 'Closed';
$lang->productplan->statusList['wait'] = 'Wait';
$lang->productplan->statusList['doing'] = 'Doing';
$lang->productplan->statusList['done'] = 'Done';
$lang->productplan->statusList['closed'] = 'Closed';
$lang->productplan->orderList['begin_desc'] = 'Begin Descend';
$lang->productplan->orderList['begin_asc'] = 'Begin Ascend';
$lang->productplan->orderList['title_desc'] = 'Title Descend';
-5
View File
@@ -142,11 +142,6 @@ $lang->productplan->featureBar['browse']['doing'] = '进行中';
$lang->productplan->featureBar['browse']['done'] = '已完成';
$lang->productplan->featureBar['browse']['closed'] = '已关闭';
$lang->productplan->statusList['wait'] = '未开始';
$lang->productplan->statusList['doing'] = '进行中';
$lang->productplan->statusList['done'] = '已完成';
$lang->productplan->statusList['closed'] = '已关闭';
$lang->productplan->orderList['begin_desc'] = '计划开始时间倒序';
$lang->productplan->orderList['begin_asc'] = '计划开始时间正序';
$lang->productplan->orderList['title_desc'] = '计划名称倒序';
+9 -2
View File
@@ -99,6 +99,7 @@ class productplanModel extends model
$planProjects = $this->dao->select('t1.*,t2.type')->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
->where('t1.product')->eq($product)
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.plan')->in(array_keys($plans))
->andWhere('t2.type')->in('sprint,stage,kanban')
->fetchPairs('plan', 'project');
@@ -1169,8 +1170,14 @@ class productplanModel extends model
if($type == 'view')
{
if(common::hasPriv('productplan', 'edit', $plan)) $menu .= html::a(helper::createLink('productplan', 'edit', $params), "<i class='icon-common-edit icon-edit'></i> " . $this->lang->edit, '', "class='btn btn-link' title='{$this->lang->edit}'");
if($plan->parent >= 0 && common::hasPriv('productplan', 'delete', $plan)) $menu .= html::a(helper::createLink('productplan', 'delete', $params), "<i class='icon-common-delete icon-trash'></i> " . $this->lang->delete, '', "class='btn btn-link' title='{$this->lang->delete}' target='hiddenwin'");
$menu .= "<div class='divider'></div>";
$menu .= $this->buildFlowMenu('productplan', $plan, $type, 'direct');
$menu .= "<div class='divider'></div>";
$editClickable = $this->buildMenu('productplan', 'edit', $params, $plan, $type, '', '', '', '', '', '', false);
$deleteClickable = $this->buildMenu('productplan', 'delete', $params, $plan, $type, '', '', '', '', '', '', false);
if(common::hasPriv('productplan', 'edit') and $editClickable) $menu .= html::a(helper::createLink('productplan', 'edit', $params), "<i class='icon-common-edit icon-edit'></i> " . $this->lang->edit, '', "class='btn btn-link' title='{$this->lang->edit}'");
if(common::hasPriv('productplan', 'delete') and $deleteClickable) $menu .= html::a(helper::createLink('productplan', 'delete', $params), "<i class='icon-common-delete icon-trash'></i> " . $this->lang->delete, '', "class='btn btn-link' title='{$this->lang->delete}' target='hiddenwin'");
}
return $menu;
+13 -11
View File
@@ -157,18 +157,20 @@
<?php echo html::commonButton($lang->edit, "data-form-action='$actionLink'");?>
<?php endif;?>
<?php if(common::hasPriv('productplan', 'batchChangeStatus')):?>
<button data-toggle="dropdown" type="button" class="btn"><?php echo $lang->productplan->planStatus;?> <span class="caret"></span></button>
<div class="dropdown-menu search-list">
<div class="list-group">
<?php
foreach($lang->productplan->statusList as $key => $status)
{
$isHiddenwin = $key == 'closed' ? '' : 'hiddenwin';
<div class="btn-group dropup">
<button data-toggle="dropdown" type="button" class="btn"><?php echo $lang->productplan->planStatus;?> <span class="caret"></span></button>
<div class="dropdown-menu search-list">
<div class="list-group">
<?php
foreach($lang->productplan->statusList as $key => $status)
{
$isHiddenwin = $key == 'closed' ? '' : 'hiddenwin';
$actionLink = $this->createLink('productplan', 'batchChangeStatus', "status=$key&productID=$product->id");
echo html::a('javascript:;', $status, '', "onclick=\"setFormAction('$actionLink', '$isHiddenwin')\"");
}
?>
$actionLink = $this->createLink('productplan', 'batchChangeStatus', "status=$key&productID=$product->id");
echo html::a('javascript:;', $status, '', "onclick=\"setFormAction('$actionLink', '$isHiddenwin')\"");
}
?>
</div>
</div>
</div>
<?php endif;?>
+2
View File
@@ -25,6 +25,8 @@ $lang->program->closedDate = 'ClosedDate';
$lang->program->canceledBy = 'CanceledBy';
$lang->program->canceledDate = 'CanceledDate';
$lang->program->lastEditedDate = 'LastEditedDate';
$lang->program->suspendedDate = 'SuspendedDate';
$lang->program->vision = 'Vision';
$lang->program->team = 'Team';
$lang->program->order = 'Rank';
$lang->program->days = 'Days';
+2
View File
@@ -25,6 +25,8 @@ $lang->program->closedDate = '关闭日期';
$lang->program->canceledBy = '由谁取消';
$lang->program->canceledDate = '取消日期';
$lang->program->lastEditedDate = '最后编辑';
$lang->program->suspendedDate = '暂停日期';
$lang->program->vision = '界面';
$lang->program->team = '团队';
$lang->program->order = '排序';
$lang->program->days = '可用工作日';
+87
View File
@@ -1499,4 +1499,91 @@ class programModel extends model
$this->lang->switcherMenu = $this->getSwitcher($programID);
common::setMenuVars('program', $programID);
}
/**
* Build program action menu.
*
* @param object $program
* @param string $type
* @access public
* @return string
*/
public function buildOperateMenu($program, $type = 'view')
{
$menu = '';
$params = "programID=$program->id";
if($program->type == 'program' && strpos(",{$this->app->user->view->programs},", ",$program->id,") !== false)
{
if($program->status == 'wait' || $program->status == 'suspended')
{
$menu .= $this->buildMenu('program', 'start', $params, $program, $type, 'play', '', 'iframe', true, '', $this->lang->program->start);
}
if($program->status == 'doing')
{
$menu .= $this->buildMenu('program', 'close', $params, $program, $type, 'off', '', 'iframe', true);
}
if($program->status == 'closed')
{
$menu .= $this->buildMenu('program', 'activate', $params, $program, $type, 'magic', '', 'iframe', true);
}
if(common::hasPriv('program', 'suspend') || (common::hasPriv('program', 'close') && $program->status != 'doing') || (common::hasPriv('program', 'activate') && $program->status != 'closed'))
{
$menu .= "<div class='btn-group'>";
$menu .= "<button type='button' class='btn icon-caret-down dropdown-toggle' data-toggle='dropdown' title='{$this->lang->more}' style='width: 16px; padding-left: 0px;'></button>";
$menu .= "<ul class='dropdown-menu pull-right text-center' role='menu' style='min-width:auto; padding: 5px 10px;'>";
$menu .= $this->buildMenu('program', 'suspend', $params, $program, $type, 'pause', '', 'iframe', true, '', $this->lang->program->suspend);
if($program->status != 'doing') $menu .= $this->buildMenu('program', 'close', $params, $program, $type, 'off', '', 'iframe', true);
if($program->status != 'closed') $menu .= $this->buildMenu('program', 'activate', $params, $program, $type, 'magic', '', 'iframe', true);
$menu .= "</ul>";
$menu .= "</div>";
}
$disabled = $program->status == 'closed' ? 'disabled' : '';
$menu .= $this->buildMenu('program', 'edit', $params, $program, $type, 'edit');
$menu .= $this->buildMenu('program', 'create', $params, $program, $type, 'split', '', '', '', $disabled, $this->lang->program->children);
if(common::hasPriv('program', 'delete'))
{
$menu .= $this->buildMenu('program', 'delete', $params, $program, $type, 'trash', 'hiddenwin', '', '', '', $this->lang->program->delete);
}
}
else if($program->type == 'project')
{
if($program->status == 'wait' || $program->status == 'suspended')
{
$menu .= $this->buildMenu('project', 'start', $params, $program, $type, 'play', '', 'iframe', true);
}
if($program->status == 'doing') $menu .= $this->buildMenu('project', 'close', $params, $program, $type, 'off', '', 'iframe', true);
if($program->status == 'closed') $menu .= $this->buildMenu('project', 'activate', $params, $program, $type, 'magic', '', 'iframe', true);
if(common::hasPriv('project', 'suspend') || (common::hasPriv('project', 'close') && $program->status != 'doing') || (common::hasPriv('project', 'activate') && $program->status != 'closed'))
{
$menu .= "<div class='btn-group'>";
$menu .= "<button type='button' class='btn icon-caret-down dropdown-toggle' data-toggle='dropdown' title='{$this->lang->more}' style='width: 16px; padding-left: 0px;'></button>";
$menu .= "<ul class='dropdown-menu pull-right text-center' role='menu' style='min-width:auto; padding: 5px 10px;'>";
$menu .= $this->buildMenu('project', 'suspend', $params, $program, $type, 'pause', '', 'iframe', true);
if($program->status != 'doing') $menu .= $this->buildMenu('project', 'close', $params, $program, $type, 'off', '', 'iframe', true);
if($program->status != 'closed') $menu .= $this->buildMenu('project', 'activate', $params, $program, $type, 'magic', '', 'iframe', true);
$menu .= "</ul>";
$menu .= "</div>";
}
$class = $program->model == 'kanban' ? 'disabled' : '';
$menu .= $this->buildMenu('project', 'edit', $params, $program, $type, 'edit', '', 'iframe', true);
$menu .= $this->buildMenu('project', 'team', $params, $program, $type, 'group', '', $class, '', 'data-app="project"');
$menu .= $this->buildMenu('project', 'group', $params, $program, $type, 'lock', '', $class, '', 'data-app="project"');
if(common::hasPriv('project', 'manageProducts') || common::hasPriv('project', 'whitelist') || common::hasPriv('project', 'delete'))
{
$menu .= "<div class='btn-group'>";
$menu .= "<button type='button' class='btn dropdown-toggle' data-toggle='dropdown' title='{$this->lang->more}'><i class='icon-more-alt'></i></button>";
$menu .= "<ul class='dropdown-menu pull-right text-center' role='menu'>";
$menu .= $this->buildMenu('project', 'manageProducts', "$params&from=browse", $program, $type, 'link', '', $class, '', "data-app={$this->app->tab}");
$menu .= $this->buildMenu('project', 'whitelist', "$params&module=project&from=browse", $program, $type, 'shield-check', '', $class, '', "data-app='project'");
if(common::hasPriv('project','delete'))
{
$menu .= $this->buildMenu("project", "delete", $params, $program, $type, 'trash', 'hiddenwin', '', '', "data-group='program'", $this->lang->delete);
}
$menu .= "</ul>";
$menu .= "</div>";
}
}
return $menu;
}
}
+1 -48
View File
@@ -92,54 +92,7 @@
</td>
<?php foreach($extendFields as $extendField) echo "<td>" . $this->loadModel('flow')->getFieldValue($extendField, $program) . "</td>";?>
<td class='c-actions'>
<?php if($program->type == 'program' and strpos(",{$app->user->view->programs},", ",$program->id,") !== false):?>
<?php if($program->status == 'wait' || $program->status == 'suspended') common::printIcon('program', 'start', "programID=$program->id", $program, 'list', 'play', '', 'iframe', true, '', $this->lang->program->start);?>
<?php if($program->status == 'doing') common::printIcon('program', 'close', "programID=$program->id", $program, 'list', 'off', '', 'iframe', true);?>
<?php if($program->status == 'closed') common::printIcon('program', 'activate', "programID=$program->id", $program, 'list', 'magic', '', 'iframe', true);?>
<?php if(common::hasPriv('program', 'suspend') || (common::hasPriv('program', 'close') && $program->status != 'doing') || (common::hasPriv('program', 'activate') && $program->status != 'closed')):?>
<div class='btn-group'>
<button type='button' class='btn icon-caret-down dropdown-toggle' data-toggle='dropdown' title="<?php echo $this->lang->more;?>" style="width: 16px; padding-left: 0px;"></button>
<ul class='dropdown-menu pull-right text-center' role='menu' style="min-width:auto; padding: 5px 10px;">
<?php common::printIcon('program', 'suspend', "programID=$program->id", $program, 'list', 'pause', '', 'iframe', true, '', $this->lang->program->suspend);?>
<?php if($program->status != 'doing') common::printIcon('program', 'close', "programID=$program->id", $program, 'list', 'off', '', 'iframe', true);?>
<?php if($program->status != 'closed') common::printIcon('program', 'activate', "programID=$program->id", $program, 'list', 'magic', '', 'iframe', true);?>
</ul>
</div>
<?php endif;?>
<?php common::printIcon('program', 'edit', "programID=$program->id", '', 'list', 'edit');?>
<?php common::printIcon('program', 'create', "programID=$program->id", '', 'list', 'split', '', '', '', $program->status == 'closed' ? 'disabled' : '', $this->lang->program->children);?>
<?php if(common::hasPriv('program', 'delete')) echo html::a($this->createLink("program", "delete", "programID=$program->id"), "<i class='icon-trash'></i>", 'hiddenwin', "class='btn' title='{$this->lang->program->delete}'");?>
<?php elseif($program->type == 'project'):?>
<?php if($program->status == 'wait' || $program->status == 'suspended') common::printIcon('project', 'start', "projectID=$program->id", $program, 'list', 'play', '', 'iframe', true);?>
<?php if($program->status == 'doing') common::printIcon('project', 'close', "projectID=$program->id", $program, 'list', 'off', '', 'iframe', true);?>
<?php if($program->status == 'closed') common::printIcon('project', 'activate', "projectID=$program->id", $program, 'list', 'magic', '', 'iframe', true);?>
<?php if(common::hasPriv('project', 'suspend') || (common::hasPriv('project', 'close') && $program->status != 'doing') || (common::hasPriv('project', 'activate') && $program->status != 'closed')):?>
<div class='btn-group'>
<button type='button' class='btn icon-caret-down dropdown-toggle' data-toggle='dropdown' title="<?php echo $this->lang->more;?>" style="width: 16px; padding-left: 0px;"></button>
<ul class='dropdown-menu pull-right text-center' role='menu' style="min-width:auto; padding: 5px 10px;">
<?php common::printIcon('project', 'suspend', "projectID=$program->id", $program, 'list', 'pause', '', 'iframe', true);?>
<?php if($program->status != 'doing') common::printIcon('project', 'close', "projectID=$program->id", $program, 'list', 'off', '', 'iframe', true);?>
<?php if($program->status != 'closed') common::printIcon('project', 'activate', "projectID=$program->id", $program, 'list', 'magic', '', 'iframe', true);?>
</ul>
</div>
<?php endif;?>
<?php $class = $program->model == 'kanban' ? 'disabled' : '';?>
<?php common::printIcon('project', 'edit', "projectID=$program->id", $program, 'list', 'edit', '', 'iframe', true);?>
<?php common::printIcon('project', 'team', "projectID=$program->id", $program, 'list', 'group', '', "$class", '', 'data-app="project"');?>
<?php common::printIcon('project', 'group', "projectID=$program->id", $program, 'list', 'lock', '', "$class", '', 'data-app="project"');?>
<?php if(common::hasPriv('project', 'manageProducts') || common::hasPriv('project', 'whitelist') || common::hasPriv('project', 'delete')):?>
<div class='btn-group'>
<button type='button' class='btn dropdown-toggle' data-toggle='dropdown' title="<?php echo $this->lang->more;?>"><i class='icon-more-alt'></i></button>
<ul class='dropdown-menu pull-right text-center' role='menu'>
<?php common::printIcon('project', 'manageProducts', "projectID=$program->id&from=browse", $program, 'list', 'link', '', "$class", '', "data-app={$this->app->tab}");?>
<?php common::printIcon('project', 'whitelist', "projectID=$program->id&module=project&from=browse", $program, 'list', 'shield-check', '', "$class", '', "data-app='project'");?>
<?php if(common::hasPriv('project','delete')) echo html::a($this->createLink("project", "delete", "projectID=$program->id"), "<i class='icon-trash'></i>", 'hiddenwin', "class='btn' title='{$this->lang->delete}' data-group='program'");?>
</ul>
</div>
<?php endif;?>
<?php endif;?>
<?php echo $this->program->buildOperateMenu($program, 'browse');?>
</td>
</tr>
<?php endforeach;?>
+1
View File
@@ -87,6 +87,7 @@
<th><?php echo $lang->project->realBegan;?></th>
<td><?php echo html::input('realBegan', helper::isZeroDate($program->realBegan) ? '' : $program->realBegan, "class='form-control form-date'");?></td>
</tr>
<?php $this->printExtendFields($program, 'table');?>
<tr>
<th><?php echo $lang->program->desc;?></th>
<td colspan='3'>
+2
View File
@@ -16,6 +16,8 @@ $lang->programplan->list = 'Stage List';
$lang->programplan->create = 'Create';
$lang->programplan->edit = 'Edit';
$lang->programplan->delete = 'Delete Stage';
$lang->programplan->close = 'Close Stage';
$lang->programplan->activate = 'Activate Stage';
$lang->programplan->createSubPlan = 'Create Sub Stage';
$lang->programplan->parent = 'Parent Stage';
+2
View File
@@ -16,6 +16,8 @@ $lang->programplan->list = '阶段列表';
$lang->programplan->create = '设置阶段';
$lang->programplan->edit = '编辑';
$lang->programplan->delete = '删除阶段';
$lang->programplan->close = '关闭阶段';
$lang->programplan->activate = '激活阶段';
$lang->programplan->createSubPlan = '创建二级阶段';
$lang->programplan->parent = '父阶段';
+9 -3
View File
@@ -429,7 +429,9 @@ class project extends control
}
}
$this->executeHooks($projectID);
$message = $this->executeHooks($projectID);
if($message) $this->lang->saveSuccess = $message;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $projectID));
if($this->app->tab != 'project' and $this->session->createProjectLocate)
@@ -585,7 +587,9 @@ class project extends control
$this->loadModel('productplan')->linkProject($projectID, $newPlans);
}
$this->executeHooks($projectID);
$message = $this->executeHooks($projectID);
if($message) $this->lang->saveSuccess = $message;
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
$locateLink = ($this->session->projectList and $from != 'view') ? $this->session->projectList : inLink('view', "projectID=$projectID");
@@ -1768,7 +1772,9 @@ class project extends control
$url = $this->createLink('project', 'browse');
if($this->app->tab == 'program') $url = $this->createLink('program', 'browse');
$this->executeHooks($projectID);
$message = $this->executeHooks($projectID);
if($message) $this->lang->saveSuccess = $message;
if(empty($executionIdList))
{
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess));
+1 -1
View File
@@ -224,7 +224,7 @@ function loadPlans(product, branchID)
if(productID != 0)
{
$.get(createLink('product', 'ajaxGetPlans', "productID=" + productID + '&branch=0,' + branchID + '&planID=0&fieldID&needCreate=&expired=unexpired|noclosed&param=skipParent'), function(data)
$.get(createLink('product', 'ajaxGetPlans', "productID=" + productID + '&branch=0,' + branchID + '&planID=0&fieldID&needCreate=&expired=unexpired,noclosed&param=skipParent'), function(data)
{
if(data)
{
+4
View File
@@ -106,6 +106,10 @@ $lang->project->teamAction = 'Team List';
$lang->project->order = 'Rank';
$lang->project->budget = 'Budget';
$lang->project->budgetUnit = 'Budget Unit';
$lang->project->suspendedDate = 'SuspendedDate';
$lang->project->vision = 'Vision';
$lang->project->displayCards = 'Max cards per column';
$lang->project->fluidBoard = 'Column Width';
$lang->project->template = 'Template';
$lang->project->estimate = 'Estimates';
$lang->project->consume = 'Cost';
+4
View File
@@ -106,6 +106,10 @@ $lang->project->teamAction = '团队列表';
$lang->project->order = '排序';
$lang->project->budget = '预算';
$lang->project->budgetUnit = '预算单位';
$lang->project->suspendedDate = '暂停日期';
$lang->project->vision = '界面';
$lang->project->displayCards = '每列最大卡片数';
$lang->project->fluidBoard = '列宽度';
$lang->project->template = '项目模板';
$lang->project->estimate = '预计';
$lang->project->consume = '消耗';
+2 -1
View File
@@ -1313,7 +1313,7 @@ class projectModel extends model
->setIF($this->post->begin == '0000-00-00', 'begin', '')
->setIF($this->post->end == '0000-00-00', 'end', '')
->setIF($this->post->future, 'budget', 0)
->setIF($this->post->budget != 0, 'budget', round($this->post->budget, 2))
->setIF($this->post->budget != 0, 'budget', round((float)$this->post->budget, 2))
->setIF(!isset($_POST['whitelist']), 'whitelist', '')
->join('whitelist', ',')
->stripTags($this->config->project->editor->edit['id'], $this->config->allowedTags)
@@ -1386,6 +1386,7 @@ class projectModel extends model
->checkFlow()
->where('id')->eq($projectID)
->exec();
if(dao::isError()) return false;
/* Get team and language item. */
$this->loadModel('user');
+1 -17
View File
@@ -71,23 +71,7 @@
<td class="c-url" title="<?php echo $build->filePath?>"><?php echo strpos($build->filePath, 'http') === 0 ? html::a($build->filePath) : $build->filePath;?></td>
<td class="c-date"><?php echo $build->date?></td>
<td class="c-user em"><?php echo zget($users, $build->builder);?></td>
<td class="c-actions">
<?php
if(common::hasPriv('build', 'linkstory') and common::hasPriv('build', 'view') and common::canBeChanged('build', $build))
{
echo html::a($this->createLink('build', 'view', "buildID=$build->id&type=story&link=true"), "<i class='icon icon-link'></i>", '', "class='btn' title='{$lang->build->linkStory}' data-app='project'");
}
common::printIcon('testtask', 'create', "product=$build->product&executionID={$build->execution}&build=$build->id&projectID=$projectID", $build, 'list', 'bullhorn', '', '', '', "data-app='project'");
$lang->build->view = $lang->project->bug;
common::printIcon('build', 'view', "buildID=$build->id&type=generatedBug", $build, 'list', 'bug', '', '', '', "data-app='project'");
common::printIcon('build', 'edit', "buildID=$build->id", $build, 'list');
if(common::hasPriv('build', 'delete', $build))
{
$deleteURL = $this->createLink('build', 'delete', "buildID=$build->id&confirm=yes");
echo html::a("###", '<i class="icon-trash"></i>', '', "onclick='ajaxDelete(\"$deleteURL\", \"buildList\", confirmDelete)' class='btn' title='{$lang->build->delete}'");
}
?>
</td>
<td class="c-actions"><?php echo $this->build->buildOperateMenu($build, 'browse');?></td>
</tr>
<?php endforeach;?>
<?php endforeach;?>
+9 -3
View File
@@ -109,7 +109,9 @@ class projectrelease extends control
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->loadModel('action')->create('release', $releaseID, 'opened');
$this->executeHooks($releaseID);
$message = $this->executeHooks($releaseID);
if($message) $this->lang->saveSuccess = $message;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $releaseID));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('view', "releaseID=$releaseID")));
@@ -161,7 +163,10 @@ class projectrelease extends control
$actionID = $this->loadModel('action')->create('release', $releaseID, 'Edited', $fileAction);
if(!empty($changes)) $this->action->logHistory($actionID, $changes);
}
$this->executeHooks($releaseID);
$message = $this->executeHooks($releaseID);
if($message) $this->lang->saveSuccess = $message;
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('view', "releaseID=$releaseID")));
}
@@ -328,7 +333,8 @@ class projectrelease extends control
$build = $this->dao->select('*')->from(TABLE_BUILD)->where('id')->eq((int)$release->build)->fetch();
if(empty($build->execution)) $this->loadModel('build')->delete(TABLE_BUILD, $build->id);
$this->executeHooks($releaseID);
$message = $this->executeHooks($releaseID);
if($message) $response['message'] = $message;
/* if ajax request, send result. */
if($this->server->ajax)
+81
View File
@@ -226,4 +226,85 @@ class projectreleaseModel extends model
if($action == 'notify') return $release->bugs or $release->stories;
return true;
}
/**
* Build project release action menu.
*
* @param object $release
* @param string $type
* @access public
* @return string
*/
public function buildOperateMenu($release, $type = 'view')
{
$function = 'buildOperate' . ucfirst($type) . 'Menu';
return $this->$function($release);
}
/**
* Build project release view action menu.
*
* @param object $release
* @access public
* @return string
*/
public function buildOperateViewMenu($release)
{
$canBeChanged = common::canBeChanged('projectrelease', $release);
if($release->deleted || !$canBeChanged || isonlybody()) return '';
$menu = '';
$params = "releaseID=$release->id";
if(common::hasPriv('projectrelease', 'changeStatus', $release))
{
$changedStatus = $release->status == 'normal' ? 'terminate' : 'normal';
$menu .= html::a(inlink('changeStatus', "$params&status=$changedStatus"), '<i class="icon-' . ($release->status == 'normal' ? 'pause' : 'play') . '"></i> ' . $this->lang->release->changeStatusList[$changedStatus], 'hiddenwin', "class='btn btn-link' title='{$this->lang->release->changeStatusList[$changedStatus]}'");
}
$menu .= "<div class='divider'></div>";
$menu .= $this->buildFlowMenu('release', $release, 'view', 'direct');
$menu .= "<div class='divider'></div>";
$editClickable = $this->buildMenu('projectrelease', 'edit', $params, $release, 'view', '', '', '', '', '', '', false);
$deleteClickable = $this->buildMenu('projectrelease', 'delete', $params, $release, 'view', '', '', '', '', '', '', false);
if(common::hasPriv('projectrelease', 'edit') and $editClickable) $menu .= html::a(helper::createLink('projectrelease', 'edit', $params), "<i class='icon-common-edit icon-edit'></i> " . $this->lang->edit, '', "class='btn btn-link' title='{$this->lang->edit}'");
if(common::hasPriv('projectrelease', 'delete') and $deleteClickable) $menu .= html::a(helper::createLink('projectrelease', 'delete', $params), "<i class='icon-common-delete icon-trash'></i> " . $this->lang->delete, '', "class='btn btn-link' title='{$this->lang->delete}' target='hiddenwin'");
return $menu;
}
/**
* Build project release browse action menu.
*
* @param object $release
* @access public
* @return string
*/
public function buildOperateBrowseMenu($release)
{
$canBeChanged = common::canBeChanged('projectrelease', $release);
if(!$canBeChanged) return '';
$menu = '';
$params = "releaseID=$release->id";
$changedStatus = $release->status == 'normal' ? 'terminate' : 'normal';
if(common::hasPriv('projectrelease', 'linkStory')) $menu .= html::a(inlink('view', "$params&type=story&link=true"), '<i class="icon-link"></i> ', '', "class='btn' title='{$this->lang->release->linkStory}'");
if(common::hasPriv('projectrelease', 'linkBug')) $menu .= html::a(inlink('view', "$params&type=bug&link=true"), '<i class="icon-bug"></i> ', '', "class='btn' title='{$this->lang->release->linkBug}'");
$menu .= $this->buildMenu('projectrelease', 'changeStatus', "$params&status=$changedStatus", $release, 'browse', $release->status == 'normal' ? 'pause' : 'play', 'hiddenwin', '', '', '',$this->lang->release->changeStatusList[$changedStatus]);
$menu .= $this->buildMenu('projectrelease', 'edit', $params, $release, 'browse');
$menu .= $this->buildMenu('projectrelease', 'notify', $params, $release, 'browse', 'bullhorn', '', 'iframe', true);
$clickable = $this->buildMenu('projectrelease', 'delete', $params, $release, 'browse', '', '', '', '', '', '', false);
if(common::hasPriv('projectrelease', 'delete', $release))
{
$deleteURL = helper::createLink('projectrelease', 'delete', "$params&confirm=yes");
$class = 'btn';
if(!$clickable) $class .= ' disabled';
$menu .= html::a("javascript:ajaxDelete(\"$deleteURL\", \"releaseList\", confirmDelete)", '<i class="icon-trash"></i>', '', "class='{$class}' title='{$this->lang->release->delete}'");
}
return $menu;
}
}
+1 -22
View File
@@ -55,7 +55,6 @@
</thead>
<tbody>
<?php foreach($releases as $release):?>
<?php $canBeChanged = common::canBeChanged('projectrelease', $release);?>
<tr>
<td><?php echo html::a(inlink('view', "releaseID=$release->id"), sprintf('%03d', $release->id));?></td>
<td>
@@ -73,27 +72,7 @@
<span class="status-release status-<?php echo $release->status?>"><?php echo $status;?></span>
</td>
<?php foreach($extendFields as $extendField) echo "<td>" . $this->loadModel('flow')->getFieldValue($extendField, $release) . "</td>";?>
<td class='c-actions'>
<?php
if($canBeChanged)
{
if(common::hasPriv('projectrelease', 'linkStory')) echo html::a(inlink('view', "releaseID=$release->id&type=story&link=true"), '<i class="icon-link"></i> ', '', "class='btn' title='{$lang->release->linkStory}'");
if(common::hasPriv('projectrelease', 'linkBug')) echo html::a(inlink('view', "releaseID=$release->id&type=bug&link=true"), '<i class="icon-bug"></i> ', '', "class='btn' title='{$lang->release->linkBug}'");
if(common::hasPriv('projectrelease', 'changeStatus', $release))
{
$changedStatus = $release->status == 'normal' ? 'terminate' : 'normal';
echo html::a($this->createLink('projectrelease', 'changeStatus', "releaseID=$release->id&status=$changedStatus"), '<i class="icon-' . ($release->status == 'normal' ? 'pause' : 'play') . '"></i> ', 'hiddenwin', "class='btn' title='{$lang->release->changeStatusList[$changedStatus]}'");
}
common::printIcon('projectrelease', 'edit', "release=$release->id", $release, 'list');
common::printIcon('projectrelease', 'notify', "release=$release->id", $release, 'list', 'bullhorn', '', 'iframe', true);
if(common::hasPriv('projectrelease', 'delete', $release))
{
$deleteURL = $this->createLink('projectrelease', 'delete', "releaseID=$release->id&confirm=yes");
echo html::a("javascript:ajaxDelete(\"$deleteURL\", \"releaseList\", confirmDelete)", '<i class="icon-trash"></i>', '', "class='btn' title='{$lang->release->delete}'");
}
}
?>
</td>
<td class='c-actions'><?php echo $this->projectrelease->buildOperateMenu($release, 'browse');?></td>
</tr>
<?php endforeach;?>
</tbody>
+2 -18
View File
@@ -29,24 +29,8 @@
<?php endif; ?>
</div>
</div>
<div class='btn-toolbar pull-right'>
<?php
$canBeChanged = common::canBeChanged('projectrelease', $release);
if(!$release->deleted and $canBeChanged)
{
echo $this->buildOperateMenu($release, 'view');
if(common::hasPriv('projectrelease', 'changeStatus', $release))
{
$changedStatus = $release->status == 'normal' ? 'terminate' : 'normal';
echo html::a(inlink('changeStatus', "releaseID=$release->id&status=$changedStatus"), '<i class="icon-' . ($release->status == 'normal' ? 'pause' : 'play') . '"></i> ' . $lang->release->changeStatusList[$changedStatus], 'hiddenwin', "class='btn btn-link' title='{$lang->release->changeStatusList[$changedStatus]}'");
}
if(common::hasPriv('projectrelease', 'edit')) echo html::a(inlink('edit', "releaseID=$release->id"), "<i class='icon-common-edit icon-edit'></i> " . $this->lang->edit, '', "class='btn btn-link' title='{$this->lang->edit}'");
if(common::hasPriv('projectrelease', 'delete')) echo html::a(inlink('delete', "releaseID=$release->id"), "<i class='icon-common-delete icon-trash'></i> " . $this->lang->delete, '', "class='btn btn-link' title='{$this->lang->delete}' target='hiddenwin'");
}
?>
</div>
<?php $canBeChanged = common::canBeChanged('projectrelease', $release);?>
<div class='btn-toolbar pull-right'><?php echo $this->projectrelease->buildOperateMenu($release, 'view');?></div>
</div>
<div id='mainContent' class='main-content'>
<div class='main-col'>
+8 -3
View File
@@ -72,7 +72,8 @@ class release extends control
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->loadModel('action')->create('release', $releaseID, 'opened');
$this->executeHooks($releaseID);
$message = $this->executeHooks($releaseID);
if($message) $this->lang->saveSuccess = $message;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $releaseID));
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.loadProductBuilds($productID)"));
@@ -126,7 +127,10 @@ class release extends control
$actionID = $this->loadModel('action')->create('release', $releaseID, 'Edited', $fileAction);
if(!empty($changes)) $this->action->logHistory($actionID, $changes);
}
$this->executeHooks($releaseID);
$message = $this->executeHooks($releaseID);
if($message) $this->lang->saveSuccess = $message;
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('view', "releaseID=$releaseID")));
}
$this->loadModel('story');
@@ -285,7 +289,8 @@ class release extends control
$build = $this->dao->select('*')->from(TABLE_BUILD)->where('id')->eq((int)$release->build)->fetch();
if(empty($build->execution)) $this->loadModel('build')->delete(TABLE_BUILD, $build->id);
$this->executeHooks($releaseID);
$message = $this->executeHooks($releaseID);
if($message) $response['message'] = $message;
/* if ajax request, send result. */
if($this->server->ajax)
+8 -3
View File
@@ -710,8 +710,10 @@ class releaseModel extends model
$menu .= $this->buildFlowMenu('release', $release, 'view', 'direct');
$menu .= "<div class='divider'></div>";
$menu .= $this->buildMenu('release', 'edit', $params, $release, 'view');
$menu .= $this->buildMenu('release', 'delete', $params, $release, 'view', 'trash', 'hiddenwin');
$editClickable = $this->buildMenu('release', 'edit', $params, $release, 'view', '', '', '', '', '', '', false);
$deleteClickable = $this->buildMenu('release', 'delete', $params, $release, 'view', '', '', '', '', '', '', false);
if(common::hasPriv('release', 'edit') and $editClickable) $menu .= html::a(helper::createLink('release', 'edit', $params), "<i class='icon-common-edit icon-edit'></i> " . $this->lang->edit, '', "class='btn btn-link' title='{$this->lang->edit}'");
if(common::hasPriv('release', 'delete') and $deleteClickable) $menu .= html::a(helper::createLink('release', 'delete', $params), "<i class='icon-common-delete icon-trash'></i> " . $this->lang->delete, '', "class='btn btn-link' title='{$this->lang->delete}' target='hiddenwin'");
return $menu;
}
@@ -737,11 +739,14 @@ class releaseModel extends model
$menu .= $this->buildMenu('release', 'changeStatus', "$params&status=$changedStatus", $release, 'browse', $release->status == 'normal' ? 'pause' : 'play', 'hiddenwin', '', '', '',$this->lang->release->changeStatusList[$changedStatus]);
$menu .= $this->buildMenu('release', 'edit', "release=$release->id", $release, 'browse');
$menu .= $this->buildMenu('release', 'notify', "release=$release->id", $release, 'browse', 'bullhorn', '', 'iframe', true);
$clickable = $this->buildMenu('release', 'delete', "release=$release->id", $release, 'browse', '', '', '', '', '', '', false);
if(common::hasPriv('release', 'delete', $release))
{
$deleteURL = helper::createLink('release', 'delete', "releaseID=$release->id&confirm=yes");
$menu .= html::a("javascript:ajaxDelete(\"$deleteURL\", \"releaseList\", confirmDelete)", '<i class="icon-trash"></i>', '', "class='btn' title='{$this->lang->release->delete}'");
$class = 'btn';
if(!$clickable) $class .= ' disabled';
$menu .= html::a("javascript:ajaxDelete(\"$deleteURL\", \"releaseList\", confirmDelete)", '<i class="icon-trash"></i>', '', "class='{$class}' title='{$this->lang->release->delete}'");
}
return $menu;
+1 -1
View File
@@ -77,7 +77,7 @@ class settingModel extends model
$item->section = $section;
$item->key = $key;
$item->value = $value;
$item->vision = empty($vision) ? '' : $vision;
if(!empty($vision)) $item->vision = $vision;
$this->dao->replace(TABLE_CONFIG)->data($item)->exec();
}
+2
View File
@@ -43,6 +43,8 @@ $config->story->list->customCreateFields = 'source,verify,pri,estimate,mail
$config->story->list->customBatchCreateFields = 'plan,spec,source,verify,pri,estimate,review,keywords';
$config->story->list->customBatchEditFields = 'branch,plan,estimate,pri,assignedTo,source,stage,closedBy,closedReason,keywords';
$config->story->list->actionsOpratedParentStory = ',edit,batchcreate,change,review,recall,';
$config->story->custom = new stdclass();
$config->story->custom->createFields = $config->story->list->customCreateFields;
$config->story->custom->batchCreateFields = 'module,plan,spec,pri,estimate,review,%s';
+3 -2
View File
@@ -178,7 +178,8 @@ class story extends control
$this->action->create('todo', $todoID, 'finished', '', "STORY:$storyID");
}
$this->executeHooks($storyID);
$message = $this->executeHooks($storyID);
if($message) $this->lang->saveSuccess = $message;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $storyID));
@@ -205,7 +206,7 @@ class story extends control
setcookie('storyModuleParam', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, true);
$execution = $this->dao->findById((int)$objectID)->from(TABLE_EXECUTION)->fetch();
$moduleName = $execution->type == 'project' ? 'projectstory' : 'execution';
$param = $execution->type == 'project' ? "projectID=$objectID&productID=$productID" : "executionID=$objectID&orderBy=id_desc&browseType=unclosed";
$param = $execution->type == 'project' ? "projectID=$objectID&productID=$productID" : "executionID=$objectID&orderBy=order_desc&browseType=unclosed";
$response['locate'] = $this->createLink($moduleName, 'story', $param);
}
if($this->app->getViewType() == 'xhtml') $response['locate'] = $this->createLink('story', 'view', "storyID=$storyID", 'html');
+7 -4
View File
@@ -3775,10 +3775,10 @@ class storyModel extends model
{
$action = strtolower($action);
if($story->parent < 0 and $action != 'edit' and $action != 'batchcreate' and $action != 'change' and $action != 'review') return false;
global $app, $config;
if($story->parent < 0 and strpos($config->story->list->actionsOpratedParentStory, ",$action,") === false) return false;
$story->reviewer = isset($story->reviewer) ? $story->reviewer : array();
$story->notReview = isset($story->notReview) ? $story->notReview : array();
@@ -3840,7 +3840,7 @@ class storyModel extends model
$menu .= $this->buildMenu('story', 'recall', $params, $story, $type, 'undo', '', 'showinonlybody');
$menu .= $this->buildMenu('story', 'review', $params, $story, $type, 'search', '', 'showinonlybody');
if(!isonlybody()) $menu .= $this->buildMenu('story', 'batchCreate', "productID=$story->product&branch=$story->branch&moduleID=$story->module&$params", $story, $type, 'split', '', 'divideStory', '', "data-toggle='modal' data-type='iframe' data-width='95%'", $this->lang->story->subdivide);
if(!isonlybody()) $menu .= $this->buildMenu('story', 'batchCreate', "productID=$story->product&branch=$story->branch&moduleID=$story->module&$params", $story, $type, 'split', '', 'divideStory', true, "data-toggle='modal' data-type='iframe' data-width='95%'", $this->lang->story->subdivide);
$menu .= $this->buildMenu('story', 'assignTo', $params, $story, $type, '', '', 'iframe showinonlybody', true);
$menu .= $this->buildMenu('story', 'close', $params, $story, $type, '', '', 'iframe showinonlybody', true);
@@ -3877,6 +3877,9 @@ class storyModel extends model
if($this->app->tab == 'execution' and strpos('draft,closed', $story->status) === false) $menu .= $this->buildMenu('task', 'create', "execution={$this->session->project}&{$params}&moduleID=$story->module", $story, $type, 'plus', '', 'showinonly body');
$menu .= "<div class='divider'></div>";
$menu .= $this->buildFlowMenu('story', $story, $type, 'direct');
$menu .= "<div class='divider'></div>";
$menu .= $this->buildMenu('story', 'edit', $params, $story, $type);
$menu .= $this->buildMenu('story', 'create', "productID=$story->product&branch=$story->branch&moduleID=$story->module&{$params}&executionID=0&bugID=0&planID=0&todoID=0&extra=&type=$story->type", $story, $type, 'copy', '', '', ' ', "data-width='1050'");
$menu .= $this->buildMenu('story', 'delete', $params, $story, 'button', 'trash', 'hiddenwin', 'showinonlybody', true);
@@ -4882,7 +4885,7 @@ class storyModel extends model
/* Merge to get a new sort list. */
$newSortIDList = array_merge($frontStoryIDList, $sortIDList, $behindStoryIDList);
if(strpos($orderBy, 'order_desc')) array_reverse($newSortIDList);
if(strpos($orderBy, 'order_desc') !== false) $newSortIDList = array_reverse($newSortIDList);
/* Loop update the story order of plan. */
$order = 1;
+1 -6
View File
@@ -116,12 +116,7 @@
<td class='<?php echo zget($visibleFields, 'keywords', 'hidden')?>'><?php echo html::input('keywords[$id]', '', "class='form-control'");?></td>
<?php
$this->loadModel('flow');
foreach($extendFields as $extendField)
{
$object = new stdclass();
$object->{$extendField->field} = $extendField->default;
echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, $object, $extendField->field . '[$id]') . "</td>";
}
foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . '[$id]') . "</td>";
?>
</tr>
</tbody>
+5 -8
View File
@@ -436,19 +436,16 @@
$executionName = $executions[$task->execution];
$taskInfo = $task->id . '&nbsp<span class="label label-success label-outline">' . $this->lang->task->statusList[$task->status] . '</span>&nbsp' . $task->name;
$class = isonlybody() ? 'showinonlybody' : 'iframe';
echo "<li title='$task->name'>" . html::a($this->createLink('task', 'view', "taskID=$task->id", '', true), $taskInfo, '', "class=$class data-width='80%'");
$execution = isset($story->executions[$task->execution]) ? $story->executions[$task->execution] : '';
$execName = (isset($execution->type) and $execution->type == 'kanban' and isonlybody()) ? $executionName : html::a($this->createLink('execution', 'view', "executionID=$task->execution"), $executionName, '', "class='text-muted'");
echo $execName . '</li>';
echo "<li title='$task->name'>" . $execName . html::a($this->createLink('task', 'view', "taskID=$task->id", '', true), $taskInfo, '', "class=$class data-width='80%'") . '</li>';
}
}
if(count($story->tasks) == 0)
foreach($story->executions as $executionID => $execution)
{
foreach($story->executions as $executionID => $execution)
{
$execName = ($execution->type == 'kanban' and isonlybody()) ? $execution->name : html::a($this->createLink('execution', 'view', "executionID=$executionID"), $execution->name, '', "class='text-muted'");
echo "<li title='$execution->name'>" . $execName . '</li>';
}
if(isset($story->tasks[$executionID])) continue;
$execName = ($execution->type == 'kanban' and isonlybody()) ? $execution->name : html::a($this->createLink('execution', 'view', "executionID=$executionID"), $execution->name, '', "class='text-muted'");
echo "<li title='$execution->name'>" . $execName . '</li>';
}
?>
</ul>
Regular → Executable
+15 -1
View File
@@ -162,7 +162,8 @@ class task extends control
$this->action->create('todo', $todoID, 'finished', '', "TASK:$taskID");
}
$this->executeHooks($taskID);
$message = $this->executeHooks($taskID);
if($message) $this->lang->saveSuccess = $message;
/* Return task id when call the API. */
if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $taskID));
@@ -1382,6 +1383,19 @@ class task extends control
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if(isset($task->fromIssue) and $task->fromIssue > 0)
{
$fromIssue = $this->loadModel('issue')->getByID($task->fromIssue);
if($fromIssue->status != 'closed')
{
$confirmURL = $this->createLink('issue', 'close', "id=$task->fromIssue");
unset($_GET['onlybody']);
$cancelURL = $this->createLink('task', 'view', "taskID=$taskID");
return print(js::confirm(sprintf($this->lang->task->remindIssue, $task->fromIssue), $confirmURL, $cancelURL, 'parent', 'parent.parent'));
}
}
if($execution->type == 'kanban' and $this->app->tab == 'execution')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
Regular → Executable
+8
View File
@@ -127,6 +127,13 @@ $lang->task->lastEdited = 'EditedBy';
$lang->task->recordEstimate = 'Effort';
$lang->task->editEstimate = 'Edit Estimates';
$lang->task->deleteEstimate = 'Delete Estimates';
$lang->task->repo = 'Repo';
$lang->task->mr = 'Merge Request';
$lang->task->entry = 'Code Path';
$lang->task->lines = 'Lines';
$lang->task->v1 = 'Version A';
$lang->task->v2 = 'Version B';
$lang->task->vision = 'Vision';
$lang->task->colorTag = 'Color';
$lang->task->files = 'Files';
$lang->task->hasConsumed = 'Already Cost';
@@ -209,6 +216,7 @@ $lang->task->afterSubmit = "Next ";
$lang->task->successSaved = "Created!";
$lang->task->delayWarning = " <strong class='text-danger'> Delay %s days </strong>";
$lang->task->remindBug = "This task is converted from a bug. Do you want to update the Bug:%s?";
$lang->task->remindIssue = "This task is converted from a issue. Do you want to update the Issue:%s?";
$lang->task->confirmChangeExecution = "If you change {$lang->executionCommon}, Module, Story and AssignedTo will also be changed. Do you want to change it?";
$lang->task->confirmFinish = '"Left Hour" is 0. Do you want to change the status to "Finished"?';
$lang->task->confirmRecord = '"Left Hour" is 0. Do you want to set the task as "Finished"?';
Regular → Executable
+8
View File
@@ -127,6 +127,13 @@ $lang->task->lastEdited = '最后编辑';
$lang->task->recordEstimate = '工时';
$lang->task->editEstimate = '编辑工时';
$lang->task->deleteEstimate = '删除工时';
$lang->task->repo = '所属版本库';
$lang->task->mr = '合并请求';
$lang->task->entry = '代码路径';
$lang->task->lines = '代码行';
$lang->task->v1 = '版本1';
$lang->task->v2 = '版本2';
$lang->task->vision = '所属界面';
$lang->task->colorTag = '颜色标签';
$lang->task->files = '附件';
$lang->task->hasConsumed = '之前消耗';
@@ -209,6 +216,7 @@ $lang->task->afterSubmit = "添加之后";
$lang->task->successSaved = "成功添加,";
$lang->task->delayWarning = " <strong class='text-danger'> 延期%s天 </strong>";
$lang->task->remindBug = "该任务为Bug转化得到,是否更新Bug:%s ?";
$lang->task->remindIssue = "该任务为问题转化得到,是否更新问题:%s ?";
$lang->task->confirmChangeExecution = "修改{$lang->executionCommon}会导致相应的所属模块、相关{$lang->SRCommon}和指派人发生变化,确定吗?";
$lang->task->confirmFinish = '"预计剩余"为0,确认将任务状态改为"已完成"吗?';
$lang->task->confirmRecord = '"剩余"为0,任务将标记为"已完成",您确定吗?';
+2 -12
View File
@@ -168,12 +168,7 @@
<td <?php echo zget($visibleFields, 'pri', "class='hidden'")?>><?php echo html::select("pri[$i]", (array)$lang->task->priList, $pri, 'class=form-control');?></td>
<?php
$this->loadModel('flow');
foreach($extendFields as $extendField)
{
$object = new stdclass();
$object->{$extendField->field} = $extendField->default;
echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, $object, $extendField->field . "[$i]") . "</td>";
}
foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[$i]") . "</td>";
?>
</tr>
<?php endfor;?>
@@ -242,12 +237,7 @@
<td <?php echo zget($visibleFields, 'pri', "class='hidden'")?>><?php echo html::select("pri[%s]", (array)$lang->task->priList, $pri, 'class=form-control');?></td>
<?php
$this->loadModel('flow');
foreach($extendFields as $extendField)
{
$object = new stdclass();
$object->{$extendField->field} = $extendField->default;
echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, $object, $extendField->field . "[%s]") . "</td>";
}
foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[%s]") . "</td>";
?>
</tr>
</tbody>
+1 -1
View File
@@ -20,7 +20,7 @@ $config->testcase->export->listFields = array('type', 'stage', 'pri', 'status'
$config->testcase->exportFields = '
id, product, branch, module, story,
title, precondition, stepDesc, stepExpect, real, keywords,
pri, type, stage, status, bugsAB, resultsAB, stepNumberAB, lastRunResult, openedBy, openedDate,
pri, type, stage, status, bugsAB, resultsAB, stepNumberAB, lastRunner, lastRunDate, lastRunResult, openedBy, openedDate,
lastEditedBy, lastEditedDate, version, linkCase, files';
$config->testcase->customCreateFields = 'story,stage,pri,keywords';
+14 -19
View File
@@ -343,7 +343,8 @@ class testcase extends control
/* If the story is linked project, make the case link the project. */
$this->testcase->syncCase2Project($caseResult['caseInfo'], $caseID);
$this->executeHooks($caseID);
$message = $this->executeHooks($caseID);
if($message) $this->lang->saveSuccess = $message;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $caseID));
/* If link from no head then reload. */
@@ -1173,7 +1174,8 @@ class testcase extends control
$case = $this->testcase->getById($caseID);
$this->testcase->delete(TABLE_CASE, $caseID);
$this->executeHooks($caseID);
$message = $this->executeHooks($caseID);
if($message) $response['message'] = $message;
/* if ajax request, send result. */
if($this->server->ajax)
@@ -1453,23 +1455,15 @@ class testcase extends control
/* Get cases. */
if($this->session->testcaseOnlyCondition)
{
if($taskID)
{
$caseIDList = $this->dao->select('`case`')->from(TABLE_TESTRUN)->where('task')->eq($taskID)->fetchPairs();
$cases = $this->dao->select('*')->from(TABLE_CASE)->where($this->session->testcaseQueryCondition)->andWhere('id')->in($caseIDList)
->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi()
->orderBy($orderBy)
->beginIF($this->post->limit)->limit($this->post->limit)->fi()
->fetchAll('id');
}
else
{
$cases = $this->dao->select('*')->from(TABLE_CASE)->where($this->session->testcaseQueryCondition)
->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi()
->orderBy($orderBy)
->beginIF($this->post->limit)->limit($this->post->limit)->fi()
->fetchAll('id');
}
$caseIDList = array();
if($taskID) $caseIDList = $this->dao->select('`case`')->from(TABLE_TESTRUN)->where('task')->eq($taskID)->fetchPairs();
$cases = $this->dao->select('*')->from(TABLE_CASE)->where($this->session->testcaseQueryCondition)
->beginIF($taskID)->andWhere('id')->in($caseIDList)->fi()
->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi()
->orderBy($orderBy)
->beginIF($this->post->limit)->limit($this->post->limit)->fi()
->fetchAll('id');
}
else
{
@@ -1588,6 +1582,7 @@ class testcase extends control
if(isset($caseLang->statusList[$case->status])) $case->status = $this->processStatus('testcase', $case);
if(isset($users[$case->openedBy])) $case->openedBy = $users[$case->openedBy];
if(isset($users[$case->lastEditedBy])) $case->lastEditedBy = $users[$case->lastEditedBy];
if(isset($users[$case->lastRunner])) $case->lastRunner = $users[$case->lastRunner];
if(isset($caseLang->resultList[$case->lastRunResult])) $case->lastRunResult = $caseLang->resultList[$case->lastRunResult];
$case->bugsAB = $case->bugs; unset($case->bugs);
+1
View File
@@ -5,6 +5,7 @@
.c-story, .c-module, .c-type {width: 120px;}
.c-stage {width: 160px;}
.c-condition {width: 80px;}
.c-keywords {width: 70px;}
.c-step {width: 300px;}
.form-actions .btn {margin-right: 20px;}
.table td textarea {height: 32px;}
+2 -12
View File
@@ -109,12 +109,7 @@
<td class='<?php echo zget($visibleFields, 'review', 'hidden')?>'><?php echo html::select("needReview[$i]", $lang->testcase->reviewList, $needReview, "class='form-control'");?></td>
<?php
$this->loadModel('flow');
foreach($extendFields as $extendField)
{
$object = new stdclass();
$object->{$extendField->field} = $extendField->default;
echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, $object, $extendField->field . "[$i]") . "</td>";
}
foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[$i]") . "</td>";
?>
</tr>
<?php endfor;?>
@@ -158,12 +153,7 @@
<td class='<?php echo zget($visibleFields, 'review', 'hidden')?>'><?php echo html::select("needReview[%s]", $lang->testcase->reviewList, $needReview, "class='form-control chosen'");?></td>
<?php
$this->loadModel('flow');
foreach($extendFields as $extendField)
{
$object = new stdclass();
$object->{$extendField->field} = $extendField->default;
echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, $object, $extendField->field . "[%s]") . "</td>";
}
foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[%s]") . "</td>";
?>
</tr>
</tbody>
+10 -8
View File
@@ -31,18 +31,20 @@ $(function()
<table class='table table-form' id='showData'>
<thead>
<tr>
<?php $requiredFields = $config->testcase->create->requiredFields;?>
<th class='c-line-number'><?php echo $lang->lineNumber?></th>
<th class='c-id'><?php echo $lang->idAB?></th>
<?php if($product->type != 'normal'):?>
<th class='c-branch'><?php echo $lang->testcase->branch?></th>
<?php endif;?>
<th class='c-name required'><?php echo $lang->testcase->title?></th>
<th class='c-module'><?php echo $lang->testcase->module?></th>
<th class='c-story'><?php echo $lang->testcase->story?></th>
<th class='c-pri-box'><?php echo $lang->testcase->pri?></th>
<th class='c-type required'><?php echo $lang->testcase->type?></th>
<th class='c-stage'><?php echo $lang->testcase->stage?></th>
<th class='c-condition'><?php echo $lang->testcase->precondition?></th>
<th class='c-name <?php if(strpos(",$requiredFields,", ',title,') !== false) echo 'required';?>'><?php echo $lang->testcase->title?></th>
<th class='c-module <?php if(strpos(",$requiredFields,", ',module,') !== false) echo 'required';?>'><?php echo $lang->testcase->module?></th>
<th class='c-story <?php if(strpos(",$requiredFields,", ',story,') !== false) echo 'required';?>'><?php echo $lang->testcase->story?></th>
<th class='c-pri-box <?php if(strpos(",$requiredFields,", ',pri,') !== false) echo 'required';?>'><?php echo $lang->testcase->pri?></th>
<th class='c-type <?php if(strpos(",$requiredFields,", ',type,') !== false) echo 'required';?>'><?php echo $lang->testcase->type?></th>
<th class='c-stage <?php if(strpos(",$requiredFields,", ',stage,') !== false) echo 'required';?>'><?php echo $lang->testcase->stage?></th>
<th class='c-condition <?php if(strpos(",$requiredFields,", ',precondition,') !== false) echo 'required';?>'><?php echo $lang->testcase->precondition?></th>
<th class='c-keywords <?php if(strpos(",$requiredFields,", ',keywords,') !== false) echo 'required';?>'><?php echo $lang->testcase->keywords?></th>
<?php if(!empty($appendFields)):?>
<?php foreach($appendFields as $appendField):?>
<th class='c-extend'><?php echo $lang->testcase->{$appendField->field}?></th>
@@ -79,7 +81,6 @@ $(function()
echo "<sub class='gray' style='vertical-align:sub;'>{$lang->testcase->new}</sub>";
}
echo html::hidden("product[$key]", $productID);
echo html::hidden("keywords[$key]", isset($case->keywords) ? $case->keywords : "");
?>
</td>
<?php $branchID = $branch;?>
@@ -104,6 +105,7 @@ $(function()
<td><?php echo html::select("type[$key]", $lang->testcase->typeList, isset($case->type) ? $case->type : '', "class='form-control chosen'")?></td>
<td style='overflow:visible'><?php echo html::select("stage[$key][]", $lang->testcase->stageList, !empty($case->stage) ? $case->stage : ((!empty($case->id) and isset($cases[$case->id])) ? $cases[$case->id]->stage : ''), "multiple='multiple' class='form-control chosen'")?></td>
<td><?php echo html::textarea("precondition[$key]", isset($case->precondition) ? htmlSpecialString($case->precondition) : "", "class='form-control'")?></td>
<td><?php echo html::input("keywords[$key]", isset($case->keywords) ? $case->keywords : '', "class='form-control'")?></td>
<?php if(!empty($appendFields)):?>
<?php $this->loadModel('flow');?>
<?php foreach($appendFields as $appendField):?>
+6 -3
View File
@@ -118,7 +118,8 @@ class testsuite extends control
}
$actionID = $this->loadModel('action')->create('testsuite', $suiteID, 'opened');
$this->executeHooks($suiteID);
$message = $this->executeHooks($suiteID);
if($message) $response['message'] = $message;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $suiteID));
@@ -221,7 +222,8 @@ class testsuite extends control
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($suiteID);
$messgae = $this->executeHooks($suiteID);
if($message) $response['message'] = $message;
$response['locate'] = inlink('view', "suiteID=$suiteID");
return $this->send($response);
@@ -263,7 +265,8 @@ class testsuite extends control
$this->testsuite->delete($suiteID);
$this->executeHooks($suiteID);
$message = $this->executeHooks($suiteID);
if($message) $response['message'] = $message;
/* if ajax request, send result. */
if($this->server->ajax)
+15 -7
View File
@@ -217,7 +217,9 @@ class testtask extends control
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->loadModel('action')->create('testtask', $taskID, 'opened');
$this->executeHooks($taskID);
$message = $this->executeHooks($taskID);
if($message) $this->lang->saveSuccess = $message;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $taskID));
$task = $this->dao->findById($taskID)->from(TABLE_TESTTASK)->fetch();
@@ -726,7 +728,8 @@ class testtask extends control
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($taskID);
$message = $this->executeHooks($taskID);
if($message) $this->lang->saveSuccess = $message;
$link = isonlybody() ? 'parent' : $this->session->testtaskList;
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $link));
@@ -788,7 +791,8 @@ class testtask extends control
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($taskID);
$message = $this->executeHooks($taskID);
if($message) $this->lang->saveSuccess = $message;
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('testtask', 'view', "taskID=$taskID")));
@@ -830,7 +834,8 @@ class testtask extends control
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($taskID);
$message = $this->executeHooks($taskID);
if($message) $this->lang->saveSuccess = $message;
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('testtask', 'view', "taskID=$taskID")));
@@ -872,7 +877,8 @@ class testtask extends control
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($taskID);
$message = $this->executeHooks($taskID);
if($message) $this->lang->saveSuccess = $message;
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent.parent'));
return $this->send(array('result' => 'success', 'message' => $this->lang->success, 'locate' => $this->createLink('testtask', 'view', "taskID=$taskID")));
@@ -915,7 +921,8 @@ class testtask extends control
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($taskID);
$message = $this->executeHooks($taskID);
if($message) $this->lang->saveSuccess = $message;
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('testtask', 'view', "taskID=$taskID")));
@@ -956,7 +963,8 @@ class testtask extends control
$task = $this->testtask->getByID($taskID);
$this->testtask->delete(TABLE_TESTTASK, $taskID);
$this->executeHooks($taskID);
$message = $this->executeHooks($taskID);
if($message) $response['message'] = $message;
/* if ajax request, send result. */
if($this->server->ajax)
+14 -11
View File
@@ -2168,10 +2168,10 @@ class testtaskModel extends model
}
/**
* Build test task menu.
*
* @param object $task
* @param string $type
* Build test task menu.
*
* @param object $task
* @param string $type
* @access public
* @return string
*/
@@ -2182,9 +2182,9 @@ class testtaskModel extends model
}
/**
* Build test task view menu.
*
* @param object $task
* Build test task view menu.
*
* @param object $task
* @access public
* @return string
*/
@@ -2208,14 +2208,14 @@ class testtaskModel extends model
$menu .= $this->buildMenu('testtask', 'edit', $params, $task, 'view');
$menu .= $this->buildMenu('testtask', 'delete', $params, $task, 'view', 'trash', 'hiddenwin');
return $menu;
}
/**
* Build test task browse menu.
*
* @param object $task
*
* @param object $task
* @access public
* @return string
*/
@@ -2231,10 +2231,13 @@ class testtaskModel extends model
$menu .= '</div>';
$menu .= $this->buildMenu('testtask', 'view', $params, $task, 'browse', 'list-alt', '', 'iframe', true, "data-width='90%'");
$menu .= $this->buildMenu('testtask', 'edit', $params, $task, 'browse');
$clickable = $this->buildMenu('testtask', 'delete', $params, $task, 'browse', '', '', '', '', '', '', false);
if(common::hasPriv('testtask', 'delete', $task))
{
$deleteURL = helper::createLink('testtask', 'delete', "taskID=$task->id&confirm=yes");
$menu .= html::a("javascript:ajaxDelete(\"$deleteURL\",\"taskList\",confirmDelete)", '<i class="icon-common-delete icon-trash"></i>', '', "title='{$this->lang->testtask->delete}' class='btn'");
$class = 'btn';
if(!$clickable) $class .= ' disabled';
$menu .= html::a("javascript:ajaxDelete(\"$deleteURL\",\"taskList\",confirmDelete)", '<i class="icon-common-delete icon-trash"></i>', '', "title='{$this->lang->testtask->delete}' class='{$class}'");
}
return $menu;
}
-6
View File
@@ -299,8 +299,6 @@ $config->delete['16_5_beta1'][] = 'module/project/ext/css/task/execl.css';
$config->delete['16_5_beta1'][] = 'module/project/ext/js/taskeffort/taskeffort.js';
$config->delete['16_5_beta1'][] = 'module/project/ext/js/effort/effort.js';
$config->delete['17_0_beta1'][] = 'extension/biz/action/ext/model/class/flow.class.php';
$config->delete['17_0_beta1'][] = 'extension/biz/action/ext/model/flow.php';
$config->delete['17_0_beta1'][] = 'extension/biz/flow/ext/control/export.php';
$config->delete['17_0_beta1'][] = 'extension/biz/flow/ext/control/exporttemplate.php';
$config->delete['17_0_beta1'][] = 'extension/biz/flow/ext/view/autoimport.html.php';
@@ -310,12 +308,9 @@ $config->delete['17_0_beta1'][] = 'extension/biz/workflowcondition/ext/view/brow
$config->delete['17_0_beta1'][] = 'extension/biz/workflowhook/ext/view/browse.html.php';
$config->delete['17_0_beta1'][] = 'extension/biz/group/ext/lang/zh-cn/aflow.php';
$config->delete['17_0_beta1'][] = 'extension/biz/group/ext/lang/zh-cn/zflow.php';
$config->delete['17_0_beta1'][] = 'extension/biz/group/ext/model/class/flow.class.php';
$config->delete['17_0_beta1'][] = 'extension/biz/group/ext/model/flow.php';
$config->delete['17_0_beta1'][] = 'extension/biz/user/ext/model/bizext.php';
$config->delete['17_0_beta1'][] = 'extension/biz/sso/ext/model/bizext.php';
$config->delete['17_0_beta1'][] = 'extension/max/action/ext/model/class/flow.class.php';
$config->delete['17_0_beta1'][] = 'extension/max/action/ext/model/flow.php';
$config->delete['17_0_beta1'][] = 'extension/max/flow/ext/control/export.php';
$config->delete['17_0_beta1'][] = 'extension/max/flow/ext/control/exporttemplate.php';
$config->delete['17_0_beta1'][] = 'extension/max/flow/ext/view/autoimport.html.php';
@@ -325,7 +320,6 @@ $config->delete['17_0_beta1'][] = 'extension/max/workflowcondition/ext/view/brow
$config->delete['17_0_beta1'][] = 'extension/max/workflowhook/ext/view/browse.html.php';
$config->delete['17_0_beta1'][] = 'extension/max/group/ext/lang/zh-cn/aflow.php';
$config->delete['17_0_beta1'][] = 'extension/max/group/ext/lang/zh-cn/zflow.php';
$config->delete['17_0_beta1'][] = 'extension/max/group/ext/model/class/flow.class.php';
$config->delete['17_0_beta1'][] = 'extension/max/group/ext/model/flow.php';
$config->delete['17_0_beta1'][] = 'extension/max/user/ext/model/bizext.php';
$config->delete['17_0_beta1'][] = 'extension/max/sso/ext/model/bizext.php';
+3
View File
@@ -652,6 +652,9 @@ class upgradeModel extends model
case 'max2_2':
$this->addDefaultKanbanPri();
break;
case 'max3_0':
$this->moveResult2Node();
break;
}
}
Regular → Executable
+8 -19
View File
@@ -35,13 +35,18 @@ class groupTest
* @access public
* @return void
*/
public function updateTest($groupID)
public function updateTest($groupID, $param)
{
$objects = $this->objectModel->update($groupID);
foreach($param as $k => $v) $_POST[$k] = $v;
$object = $this->objectModel->update($groupID);
unset($_POST);
if(dao::isError()) return dao::getError();
return $objects;
$object = $this->objectModel->getByID($groupID);
return $object;
}
/**
@@ -286,22 +291,6 @@ class groupTest
return $objects;
}
/**
* Update view priv.
*
* @param int $groupID
* @access public
* @return bool
*/
public function updateViewTest($groupID)
{
$objects = $this->objectModel->updateView($groupID);
if(dao::isError()) return dao::getError();
return $objects;
}
/**
* Update privilege by module.
*
+7 -1
View File
@@ -11,7 +11,13 @@ cid=1
pid=1
*/
$t_name = array('name' => '我是一个分组', 'desc' => '');
$t_desc = array('name' => '我是一个分组', 'desc' => '这是一个分组');
$group = new groupTest();
a($group->updateTest(2, $t_name));
r($group->updateTest()) && p() && e();
r($group->updateTest(2, $t_name)) && p('name') && e('我是一个分组'); //测试更新分组id为2的分组
r($group->updateTest(2, $t_desc)) && p('desc') && e('这是一个分组'); //测试更新分组2为受限用户分组
system("./ztest init");
Regular → Executable
+15 -3
View File
@@ -1,7 +1,6 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/group.class.php';
su('admin');
/**
@@ -12,6 +11,19 @@ pid=1
*/
$group = new groupTest();
global $tester;
$tester->loadModel('group');
r($group->updateViewTest()) && p() && e();
$_POST['allchecker'] = 1;
$tester->group->updateView(1);
$group1 = $tester->group->getByID(1);
$_POST['actions']['task']['create'] = 'create';
$tester->group->updateView(1);
$group2 = $tester->group->getByID(1);
r(count($group1->acl)) && p() && e('2'); // 针对ID为1的权限分组,设置全选权限,查看返回的数据元素数量
r(count($group2->acl)) && p() && e('3'); // 针对ID为1的权限分组,设置任务创建权限,查看返回的数据元素数量
r($group2->acl) && p('task:create') && e('create'); // 针对ID为1的权限分组,设置任务创建权限,查看是否有创建方法
system("./ztest init");
@@ -1,15 +1,18 @@
<?php
$this->loadModel('setting');
$xxItems = $this->setting->getItems('owner=system&module=common&section=xuanxuan');
$xxConfig = array();
foreach($xxItems as $xxItem) $xxConfig[$xxItem->key] = $xxItem->value;
if(empty($xxConfig['key']))
if(defined('IN_USE') or (defined('RUN_MODE') and RUN_MODE == 'api'))
{
$this->setting->setItem('system.common.xuanxuan.turnon', 0);
$this->setting->setItem('system.common.xuanxuan.key', $this->setting->computeSN());
$this->loadModel('setting');
$xxItems = $this->setting->getItems('owner=system&module=common&section=xuanxuan');
$xxConfig = array();
foreach($xxItems as $xxItem) $xxConfig[$xxItem->key] = $xxItem->value;
if(empty($xxConfig['key']))
{
$this->setting->setItem('system.common.xuanxuan.turnon', 0);
$this->setting->setItem('system.common.xuanxuan.key', $this->setting->computeSN());
}
if(!isset($xxConfig['chatPort'])) $this->setting->setItem('system.common.xuanxuan.chatPort', 11444);
if(!isset($xxConfig['commonPort'])) $this->setting->setItem('system.common.xuanxuan.commonPort', 11443);
if(!isset($xxConfig['ip'])) $this->setting->setItem('system.common.xuanxuan.ip', '0.0.0.0');
if(!isset($xxConfig['uploadFileSize'])) $this->setting->setItem('system.common.xuanxuan.uploadFileSize', 20);
if(!isset($xxConfig['https']) and !isset($xxConfig['isHttps'])) $this->setting->setItem('system.common.xuanxuan.https', 'off');
}
if(!isset($xxConfig['chatPort'])) $this->setting->setItem('system.common.xuanxuan.chatPort', 11444);
if(!isset($xxConfig['commonPort'])) $this->setting->setItem('system.common.xuanxuan.commonPort', 11443);
if(!isset($xxConfig['ip'])) $this->setting->setItem('system.common.xuanxuan.ip', '0.0.0.0');
if(!isset($xxConfig['uploadFileSize'])) $this->setting->setItem('system.common.xuanxuan.uploadFileSize', 20);
if(!isset($xxConfig['https']) and !isset($xxConfig['isHttps'])) $this->setting->setItem('system.common.xuanxuan.https', 'off');