Merge branch 'master' into 'sprint/189_mayue_task#53652'

# Conflicts:
#   module/project/model.php
This commit is contained in:
孙广明
2022-05-12 05:01:42 +00:00
74 changed files with 1715 additions and 631 deletions
+293 -159
View File
@@ -114,168 +114,302 @@ UPDATE `zt_workflowfield` SET `control` = 'date' WHERE `module` = 'story' and `f
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 `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' 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` = 'view' WHERE `module` = 'story' and `action` = 'view' 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';
INSERT INTO `zt_workflowdatasource` (`type`, `name`, `code`, `buildin`, `datasource`, `view`, `keyField`, `valueField`) VALUES('lang', '项目模型', 'projectModel', '1', 'projectModel', '', '', '');
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', '', '', '');
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
('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'),
('execution', 'days', 'smallint', '5', '可用工作日', 'integer', '', '', '', '', '', 18, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'pri', 'enum', '', '优先级', 'select', '', '[1,2,3,4]', '1', '', '', 20, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'desc', 'text', '', '迭代描述', 'richtext', '', '', '', '', '', 21, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'openedDate', 'datetime', '', '创建日期', 'datetime', '', '', '', '', '', 27, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'closedDate', 'datetime', '', '关闭日期', 'datetime', '', '', '', '', '', 32, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'canceledDate', 'datetime', '', '取消日期', 'datetime', '', '', '', '', '', 34, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'acl', 'char', '30', '访问控制', 'select', '', '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', '访问控制', 'select', '', '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'),
('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'),
('build', 'deleted', 'enum', '', '已删除', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 14, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', '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'),
('bug', 'storyVersion', 'smallint', '6', '研发需求版本', 'integer', '', '', '1', '', '', 9, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'toTask', 'mediumint', '8', '转任务', 'select', '', '5', '0', '', '', 11, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'toStory', 'mediumint', '8', '转研发需求', 'select', '', '4', '0', '', '', 12, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'steps', 'mediumtext', '', '重现步骤', 'richtext', '', '', '', '', '', 22, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'activatedDate', 'datetime', '', '激活日期', 'datetime', '', '', '', '', '', 27, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'openedDate', 'datetime', '', '创建日期', 'datetime', '', '', '', '', '', 32, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'openedBuild', 'varchar', '255', '影响版本', 'multi-select', '', '10', '', '', '', 33, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'assignedDate', 'datetime', '', '指派日期', 'datetime', '', '', '', '', '', 35, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'deadline', 'date', '', '截止日期', 'date', '', '', '', '', '', 36, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'resolvedDate', 'datetime', '30', '解决日期', 'datetime', '', '', '', '', '', 40, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'closedDate', 'datetime', '', '关闭日期', 'datetime', '', '', '', '', '', 42, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'case', 'mediumint', '8', '相关用例', 'select', '', '41', '', '', '', 45, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('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'),
('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', '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'),
('task', 'estimate', 'float ', '', '最初预计', 'decimal', '', '', '', '', '', 13, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'consumed', 'float ', '', '总计消耗', 'decimal', '', '', '', '', '', 14, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'left', 'float ', '', '预计剩余', 'decimal', '', '', '', '', '', 15, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'deadline', 'date', '', '截止日期', 'date', '', '', '', '', '', 16, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'desc', 'text', '', '任务描述', 'richtext', '', '', '', '', '', 20, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'openedDate', 'datetime', '', '创建日期', 'datetime', '', '', '', '', '', 23, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'assignedDate', 'datetime', '30', '指派日期', 'datetime', '', '', '', '', '', 25, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'estStarted', 'date', '', '预计开始', 'date', '', '', '', '', '', 26, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'realStarted', 'date', '', '实际开始', 'date', '', '', '', '', '', 27, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'finishedDate', 'datetime', '', '实际完成', 'datetime', '', '', '', '', '', 29, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'canceledDate', 'datetime', '', '取消时间', 'datetime', '', '', '', '', '', 32, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('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'),
('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', 'vision', 'varchar', '10', 'vision', 'input', '', '', 'rnd', '', '', 47, 0, 0, '0', '0', '0', '1', 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' LIMIT 1) WHERE `module`='project' AND `field`='model';
('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'),
('execution', 'days', 'smallint', '5', '可用工作日', 'integer', '', '', '', '', '', 18, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'pri', 'enum', '', '优先级', 'select', '', '[1,2,3,4]', '1', '', '', 20, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'desc', 'text', '', '迭代描述', 'richtext', '', '', '', '', '', 21, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'openedDate', 'datetime', '', '创建日期', 'datetime', '', '', '', '', '', 27, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'closedDate', 'datetime', '', '关闭日期', 'datetime', '', '', '', '', '', 32, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'canceledDate', 'datetime', '', '取消日期', 'datetime', '', '', '', '', '', 34, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('execution', 'acl', 'char', '30', '访问控制', 'select', '', '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', '访问控制', 'select', '', '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'),
('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'),
('build', 'deleted', 'enum', '', '已删除', 'radio', '', '[\"\\u672a\\u5220\\u9664\",\"\\u5df2\\u5220\\u9664\"]', '0', '', '', 14, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', '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'),
('bug', 'storyVersion', 'smallint', '6', '研发需求版本', 'integer', '', '', '1', '', '', 9, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'toTask', 'mediumint', '8', '转任务', 'select', '', '5', '0', '', '', 11, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'toStory', 'mediumint', '8', '转研发需求', 'select', '', '4', '0', '', '', 12, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'steps', 'mediumtext', '', '重现步骤', 'richtext', '', '', '', '', '', 22, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'activatedDate', 'datetime', '', '激活日期', 'datetime', '', '', '', '', '', 27, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'openedDate', 'datetime', '', '创建日期', 'datetime', '', '', '', '', '', 32, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'openedBuild', 'varchar', '255', '影响版本', 'multi-select', '', '10', '', '', '', 33, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'assignedDate', 'datetime', '', '指派日期', 'datetime', '', '', '', '', '', 35, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'deadline', 'date', '', '截止日期', 'date', '', '', '', '', '', 36, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'resolvedDate', 'datetime', '30', '解决日期', 'datetime', '', '', '', '', '', 40, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'closedDate', 'datetime', '', '关闭日期', 'datetime', '', '', '', '', '', 42, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('bug', 'case', 'mediumint', '8', '相关用例', 'select', '', '41', '', '', '', 45, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('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'),
('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', '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'),
('task', 'estimate', 'float', '', '最初预计', 'decimal', '', '', '', '', '', 13, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'consumed', 'float', '', '总计消耗', 'decimal', '', '', '', '', '', 14, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'left', 'float', '', '预计剩余', 'decimal', '', '', '', '', '', 15, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'deadline', 'date', '', '截止日期', 'date', '', '', '', '', '', 16, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'desc', 'text', '', '任务描述', 'richtext', '', '', '', '', '', 20, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'openedDate', 'datetime', '', '创建日期', 'datetime', '', '', '', '', '', 23, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'assignedDate', 'datetime', '30', '指派日期', 'datetime', '', '', '', '', '', 25, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'estStarted', 'date', '', '预计开始', 'date', '', '', '', '', '', 26, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'realStarted', 'date', '', '实际开始', 'date', '', '', '', '', '', 27, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'finishedDate', 'datetime', '', '实际完成', 'datetime', '', '', '', '', '', 29, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('task', 'canceledDate', 'datetime', '', '取消时间', 'datetime', '', '', '', '', '', 32, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('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'),
('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', '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'),
('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'),
('feedback', 'feedbackBy', 'varchar', '100', '反馈者', 'select', '', 'user', '', '', '', 25, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('feedback', 'solution', 'char', '30', '反馈处理方案', 'select', '', '', '', '', '', 5, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('testcase', 'auto', 'varchar', '10', '自动化测试用例', 'input', '', '', '', '', '', 15, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('testcase', 'frame', 'varchar', '10', '自动化测试框架', 'input', '', '', '', '', '', 16, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('testcase', 'howRun', 'char', '30', '测试方式', 'input', '', '', '', '', '', 18, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('testcase', 'scriptedBy', 'char', '30', '脚本由谁创建', 'select', '', 'user', '', '', '', 18, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('testcase', 'scriptedDate', 'char', '30', '脚本创建日期', 'date', '', '', '', '', '', 18, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('testcase', 'scriptStatus', 'char', '30', '脚本状态', 'input', '', '', '', '', '', 18, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('testcase', 'scriptLocation', 'char', '30', '脚本地址', 'input', '', '', '', '', '', 18, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('testcase', 'frequency', 'char', '30', '使用频率', 'input', '', '', '', '', '', 28, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('testcase', 'fromCaseID', 'char', '30', '用例来源ID', 'input', '', '', '', '', '', 28, 0, 0, '0', '0', '0', '1', 1, '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00'),
('testcase', 'fromCaseVersion', 'char', '30', '用例来源版本', 'input', '', '', '', '', '', 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' LIMIT 1) WHERE `module`='project' AND `field`='model';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackType' LIMIT 1) WHERE `module`='feedback' AND `field`='type';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackSolution' LIMIT 1) WHERE `module`='feedback' AND `field`='solution';
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';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='project' AND `action`='edit';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='normal', `layout`='side' WHERE `module`='project' AND `action`='view';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='dropdownlist', `open`='none', `layout`='normal' WHERE `module`='project' AND `action`='delete';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='dropdownlist', `open`='modal', `layout`='normal' WHERE `module`='project' AND `action`='close';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='dropdownlist', `open`='modal', `layout`='normal' WHERE `module`='project' AND `action`='activate';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='project' AND `action`='start';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='dropdownlist', `open`='modal', `layout`='normal' WHERE `module`='project' AND `action`='suspend';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='execution' AND `action`='task';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='execution' AND `action`='create';
UPDATE `zt_workflowaction` SET `type`='batch', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='execution' AND `action`='batchedit';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='execution' AND `action`='edit';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='execution' AND `action`='view';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='none', `layout`='normal' WHERE `module`='execution' AND `action`='delete';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='execution' AND `action`='close';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='execution' AND `action`='activate';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='execution' AND `action`='start';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='execution' AND `action`='putoff';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='execution' AND `action`='suspend';
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`='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';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='showimport';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='side' WHERE `module`='task' AND `action`='edit';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='normal', `layout`='side' WHERE `module`='task' AND `action`='view';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='none', `layout`='normal' WHERE `module`='task' AND `action`='delete';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='close';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='activate';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='assignTo';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='none', `layout`='normal' WHERE `module`='task' AND `action`='confirmStoryChange';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='start';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='finish';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='pause';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='restart';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='cancel';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='build' AND `action`='browse';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='build' AND `action`='create';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='build' AND `action`='edit';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='build' AND `action`='view';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='none', `layout`='normal' WHERE `module`='build' AND `action`='delete';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='bug' AND `action`='browse';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='bug' AND `action`='create';
UPDATE `zt_workflowaction` SET `type`='batch', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='bug' AND `action`='batchcreate';
UPDATE `zt_workflowaction` SET `type`='batch', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='bug' AND `action`='batchedit';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='bug' AND `action`='exporttemplate';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='bug' AND `action`='import';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='bug' AND `action`='showimport';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='side' WHERE `module`='bug' AND `action`='edit';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='normal', `layout`='side' WHERE `module`='bug' AND `action`='view';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='none', `layout`='normal' WHERE `module`='bug' AND `action`='delete';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='bug' AND `action`='close';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='bug' AND `action`='activate';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='bug' AND `action`='assignTo';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='bug' AND `action`='confirmBug';
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`='single', `position`='browseandview', `show`='dropdownlist', `open`='modal', `layout`='normal' WHERE `module`='project' AND `action`='activate';
UPDATE `zt_workflowaction` SET `type`='batch', `position`='browse', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='project' AND `action`='batchedit';
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`='browseandview', `show`='dropdownlist', `open`='modal', `layout`='normal' WHERE `module`='project' AND `action`='close';
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`='single', `position`='browseandview', `show`='dropdownlist', `open`='none', `layout`='normal' WHERE `module`='project' AND `action`='delete';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='project' AND `action`='edit';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='project' AND `action`='start';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='dropdownlist', `open`='modal', `layout`='normal' WHERE `module`='project' AND `action`='suspend';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='normal', `layout`='side' WHERE `module`='project' AND `action`='view';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='activate';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='assignTo';
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`='browseandview', `show`='direct', `open`='normal', `layout`='normal' WHERE `module`='task' AND `action`='browse';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='cancel';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='close';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='none', `layout`='normal' WHERE `module`='task' AND `action`='confirmStoryChange';
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`='single', `position`='view', `show`='direct', `open`='none', `layout`='normal' WHERE `module`='task' AND `action`='delete';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='normal', `layout`='side' WHERE `module`='task' AND `action`='edit';
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`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='finish';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='import';
UPDATE `zt_workflowaction` SET `type`='single', `position`='view', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='pause';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='restart';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='showimport';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browseandview', `show`='direct', `open`='modal', `layout`='normal' WHERE `module`='task' AND `action`='start';
UPDATE `zt_workflowaction` SET `type`='single', `position`='browse', `show`='direct', `open`='normal', `layout`='side' WHERE `module`='task' AND `action`='view';
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 `position`='browse' WHERE `module`IN ('feedback','caselib','testsuite','testtask','testcase') AND `action` IN ('batchedit','batchcreate','import','showimport');
+1 -4
View File
@@ -326,10 +326,7 @@ class control extends baseControl
if(!isset($this->config->bizVersion)) return false;
$moduleName = $this->moduleName;
if(strpos(',bug,feedback,caselib,testsuite,testtask,testcase,product,productplan,', ",{$moduleName},") !== false) return $this->$moduleName->buildOperateMenu($object, $type);
$flow = $this->loadModel('workflow')->getByModule($moduleName);
return $this->loadModel('flow')->buildOperateMenu($flow, $object, $type);
return $this->$moduleName->buildOperateMenu($object, $type);
}
/**
+6
View File
@@ -60,3 +60,9 @@ $config->action->majorList['execution'] = array('opened', 'edited');
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,testcase,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,';
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,';
$config->action->preferredTypeNum = 10;
$config->action->preferredType = new stdclass();
$config->action->preferredType->new = array('user', 'story', 'task', 'bug', 'case', 'doc', 'program', 'product', 'project', 'execution');
$config->action->preferredType->classic = array('user', 'story', 'task', 'bug', 'case', 'doc', 'product', 'execution', 'productplan', 'build');
+28 -8
View File
@@ -14,6 +14,7 @@ class action extends control
/**
* Trash.
*
* @param string $browseType
* @param string $type all|hidden
* @param string $orderBy
* @param int $recTotal
@@ -22,7 +23,7 @@ class action extends control
* @access public
* @return void
*/
public function trash($type = 'all', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
public function trash($browseType = 'all', $type = 'all', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->loadModel('backup');
@@ -60,18 +61,37 @@ class action extends control
$pager = pager::init($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = common::appendOrder($orderBy);
$trashes = $this->action->getTrashes($type, $sort, $pager);
$sort = common::appendOrder($orderBy);
$trashes = $this->action->getTrashes($browseType, $type, $sort, $pager);
$objectTypeList = $this->action->getTrashObjectTypes($type);
$objectTypeList = array_keys($objectTypeList);
$preferredType = array();
$moreType = array();
$preferredTypeConfig = $this->config->systemMode == 'new' ? $this->config->action->preferredType->new : $this->config->action->preferredType->classic;
foreach($objectTypeList as $objectType)
{
in_array($objectType, $preferredTypeConfig) ? $preferredType[$objectType] = $objectType : $moreType[$objectType] = $objectType;
}
if(count($preferredType) < $this->config->action->preferredTypeNum)
{
$toPreferredType = array_splice($moreType, 0, $this->config->action->preferredTypeNum - count($preferredType));
$preferredType = $preferredType + $toPreferredType;
}
/* Title and position. */
$this->view->title = $this->lang->action->trash;
$this->view->position[] = $this->lang->action->trash;
$this->view->trashes = $trashes;
$this->view->type = $type;
$this->view->orderBy = $orderBy;
$this->view->pager = $pager;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->trashes = $trashes;
$this->view->type = $type;
$this->view->currentObjectType = $browseType;
$this->view->orderBy = $orderBy;
$this->view->pager = $pager;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->preferredType = $preferredType;
$this->view->moreType = $moreType;
$this->view->preferredTypeConfig = $preferredTypeConfig;
$this->display();
}
+4
View File
@@ -1,3 +1,7 @@
.table-footer .table-actions {width: auto; visibility: visible; opacity: 1;}
.table-footer .table-actions .text {line-height: 28px;}
table tbody tr td {overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
#mainMenu .btn-toolbar .btn-group .dropdown-menu .btn-active-text:hover .text {color: #fff}
.dropdown-menu .btn-active-text:hover .text:after {border-bottom: 0px;}
+18 -2
View File
@@ -610,17 +610,19 @@ class actionModel extends model
/**
* Get deleted objects.
*
* @param string $objectType
* @param string $type all|hidden
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getTrashes($type, $orderBy, $pager)
public function getTrashes($objectType, $type, $orderBy, $pager)
{
$extra = $type == 'hidden' ? self::BE_HIDDEN : self::CAN_UNDELETED;
$extra = $type == 'hidden' ? self::BE_HIDDEN : self::CAN_UNDELETED;
$trashes = $this->dao->select('*')->from(TABLE_ACTION)
->where('action')->eq('deleted')
->beginIF($objectType != 'all')->andWhere('objectType')->eq($objectType)->fi()
->andWhere('extra')->eq($extra)
->andWhere('vision')->eq($this->config->vision)
->orderBy($orderBy)->page($pager)->fetchAll();
@@ -665,9 +667,23 @@ class actionModel extends model
$trash->objectName = isset($objectNames[$objectType][$trash->objectID]) ? $objectNames[$objectType][$trash->objectID] : '';
}
return $trashes;
}
/**
* Get object type list of trashes.
*
* @param string $type
* @access public
* @return array
*/
public function getTrashObjectTypes($type)
{
$extra = $type == 'hidden' ? self::BE_HIDDEN : self::CAN_UNDELETED;
return $this->dao->select('objectType')->from(TABLE_ACTION)->where('action')->eq('deleted')->andWhere('extra')->eq($extra)->andWhere('vision')->eq($this->config->vision)->fetchAll('objectType');
}
/**
* Get histories of an action.
*
+47 -3
View File
@@ -12,9 +12,53 @@
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<?php $activeClass = $currentObjectType == 'all' ? 'btn-active-text' : '';?>
<?php echo html::a($this->createLink('action', 'trash', "objectType=all&type=$type"), "<span class='text'>" . $lang->all . "</span>", '', "class='btn btn-link $activeClass'");?>
<?php
/* Output the objectType order by preferredTypeConfig. */
foreach($preferredTypeConfig as $objectType)
{
if(in_array($objectType, $preferredType))
{
$activeClass = $objectType == $currentObjectType ? 'btn-active-text' : '';
echo html::a($this->createLink('action', 'trash', "objectType=$objectType&type=$type"), "<span class='text'>" . zget($lang->action->objectTypes, $objectType) . "</span>", '', "class='btn btn-link $activeClass'");
unset($preferredType[$objectType]);
}
}
/* Output the remaining types which transformed from more type. */
foreach($preferredType as $objectType)
{
$activeClass = $objectType == $currentObjectType ? 'btn-active-text' : '';
echo html::a($this->createLink('action', 'trash', "objectType=$objectType&type=$type"), "<span class='text'>" . zget($lang->action->objectTypes, $objectType) . "</span>", '', "class='btn btn-link $activeClass'");
}
/* Output the more types. */
if(!empty($moreType))
{
$moreLabel = $lang->more;
$moreLabelActive = '';
if(in_array($currentObjectType, $moreType))
{
$moreLabel = "<span class='text'>" . zget($lang->action->objectTypes, $currentObjectType) . "</span>";
$moreLabelActive = 'btn-active-text';
}
echo '<div class="btn-group" id="more">';
echo html::a('javascript:;', $moreLabel . " <span class='caret'></span>", '', "data-toggle='dropdown' class='btn btn-link $moreLabelActive'");
echo "<ul class='dropdown-menu'>";
foreach($moreType as $objectType)
{
$activeClass = $objectType == $currentObjectType ? 'btn-active-text' : '';
echo '<li>' . html::a($this->createLink('action', 'trash', "objectType=$objectType&type=$type"), "<span class='text'>" . zget($lang->action->objectTypes, $objectType) . "</span>", '', "class='btn btn-link $activeClass'") . '</li>';
}
echo '</ul></div>';
}
?>
</div>
<div class='btn-toolbar pull-right'>
<?php if($type == 'hidden') echo html::a(inLink('trash', "type=all"), $lang->goback, '', "class='btn'");?>
<?php if($type == 'all') echo html::a(inLink('trash', "type=hidden"), "<i class='icon-eye-close'></i> " . $lang->action->dynamic->hidden, '', "class='btn btn-danger'");?>
<?php if($type == 'hidden') echo html::a(inLink('trash', "browseType=all&type=all"), $lang->goback, '', "class='btn'");?>
<?php if($type == 'all') echo html::a(inLink('trash', "browseType=all&type=hidden"), "<i class='icon-eye-close'></i> " . $lang->action->dynamic->hidden, '', "class='btn btn-danger'");?>
</div>
</div>
@@ -31,7 +75,7 @@
</div>
<div class='main-table' data-ride='table'>
<table class='table has-sort-head'>
<?php $vars = "type=$type&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}"; ?>
<?php $vars = "browseType=$currentObjectType&type=$type&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}"; ?>
<thead>
<tr class='colhead'>
<th class='c-object-type'><?php common::printOrderLink('objectType', $orderBy, $vars, $lang->action->objectType);?></th>
+1
View File
@@ -764,6 +764,7 @@ class apiModel extends model
public function createDemoData($name, $baseUrl, $version = '16.0')
{
/* Replace the doc lib name to api lib name. */
$this->app->loadLang('doc');
$this->lang->doclib->name = $this->lang->doclib->apiLibName;
$firstAccount = $this->dao->select('account')->from(TABLE_USER)->orderBy('id_asc')->limit(1)->fetch('account');
+37 -34
View File
@@ -1679,12 +1679,7 @@ class bugModel extends model
}
}
$allProduct = "`product` = 'all'";
$bugQuery = $this->session->projectBugQuery;
if(strpos($this->session->projectBugQuery, $allProduct) !== false)
{
$bugQuery = str_replace($allProduct, '1', $this->session->projectBugQuery);
}
$bugQuery = $this->getBugQuery($this->session->projectBugQuery);
$bugs = $this->dao->select('*')->from(TABLE_BUG)
->where($bugQuery)
@@ -1746,12 +1741,7 @@ class bugModel extends model
}
}
$allProduct = "`product` = 'all'";
$bugQuery = $this->session->executionBugQuery;
if(strpos($this->session->executionBugQuery, $allProduct) !== false)
{
$bugQuery = str_replace($allProduct, '1', $this->session->executionBugQuery);
}
$bugQuery = $this->getBugQuery($this->session->executionBugQuery);
$bugs = $this->dao->select('*')->from(TABLE_BUG)
->where($bugQuery)
@@ -2703,10 +2693,41 @@ class bugModel extends model
if($this->session->bugQuery == false) $this->session->set('bugQuery', ' 1 = 1');
}
$allProduct = "`product` = 'all'";
$bugQuery = $this->session->bugQuery;
$bugQuery = $this->getBugQuery($this->session->bugQuery);
if(is_array($productIDList)) $productIDList = implode(',', $productIDList);
if(strpos($bugQuery, '`product` =') === false) $bugQuery .= ' AND `product` in (' . $productIDList . ')';
$allBranch = "`branch` = 'all'";
if($branch !== 'all' and strpos($bugQuery, '`branch` =') === false) $bugQuery .= " AND `branch` in('0','$branch')";
if(strpos($bugQuery, $allBranch) !== false) $bugQuery = str_replace($allBranch, '1', $bugQuery);
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where($bugQuery)
->beginIF(!$this->app->user->admin)->andWhere('execution')->in('0,' . $this->app->user->view->sprints)->fi()
->beginIF($excludeBugs)->andWhere('id')->notIN($excludeBugs)->fi()
->beginIF($projectID)
->andWhere('project', true)->eq($projectID)
->orWhere('project')->eq(0)
->andWhere('openedBuild')->eq('trunk')
->markRight(1)
->fi()
->andWhere('deleted')->eq(0)
->orderBy($orderBy)->page($pager)->fetchAll();
return $bugs;
}
/**
* Get bug query.
*
* @param string $bugQuery
* @access public
* @return string
*/
public function getBugQuery($bugQuery)
{
$allProduct = "`product` = 'all'";
if(strpos($bugQuery, $allProduct) !== false)
{
$products = $this->app->user->view->products;
@@ -2714,10 +2735,6 @@ class bugModel extends model
$bugQuery = $bugQuery . ' AND `product` ' . helper::dbIN($products);
}
$allBranch = "`branch` = 'all'";
if($branch !== 'all' and strpos($bugQuery, '`branch` =') === false) $bugQuery .= " AND `branch` in('0','$branch')";
if(strpos($bugQuery, $allBranch) !== false) $bugQuery = str_replace($allBranch, '1', $bugQuery);
$allProject = "`project` = 'all'";
if(strpos($bugQuery, $allProject) !== false)
{
@@ -2745,26 +2762,12 @@ class bugModel extends model
->orWhere('t2.verify')->like("%$searchValue%")
->fetchPairs('id');
$bugQuery = preg_replace("/`story`[ ]+(NOT[ ]*)?LIKE[ ]+'%$searchValue%'/Ui", '`story` $1 IN (' . implode($story, ',') .')', $bugQuery);
$bugQuery = preg_replace("/`story`[ ]+(NOT[ ]*)?LIKE[ ]+'%$searchValue%'/Ui", '`story` $1 IN (' . implode(',', $story) .')', $bugQuery);
}
}
$bugQuery .= ' AND `story` != 0';
}
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where($bugQuery)
->beginIF(!$this->app->user->admin)->andWhere('execution')->in('0,' . $this->app->user->view->sprints)->fi()
->beginIF($excludeBugs)->andWhere('id')->notIN($excludeBugs)->fi()
->beginIF($projectID)
->andWhere('project', true)->eq($projectID)
->orWhere('project')->eq(0)
->andWhere('openedBuild')->eq('trunk')
->markRight(1)
->fi()
->andWhere('deleted')->eq(0)
->orderBy($orderBy)->page($pager)->fetchAll();
return $bugs;
return $bugQuery;
}
/**
+1 -1
View File
@@ -96,7 +96,7 @@
<?php common::printBack($browseLink);?>
<?php if(!$bug->deleted):?>
<div class='divider'></div>
<?php echo $this->buildOperateMenu($bug, 'view');?>
<?php echo $this->bug->buildOperateMenu($bug, 'view');?>
<?php endif;?>
</div>
</div>
+23 -1
View File
@@ -505,7 +505,6 @@ class buildModel extends model
*/
public function batchUnlinkBug($buildID)
{
$bugList = $this->post->unlinkBugs;
if(empty($bugList)) return true;
@@ -518,4 +517,27 @@ class buildModel extends model
$this->loadModel('action');
foreach($this->post->unlinkBugs as $unlinkBugID) $this->action->create('bug', $unlinkBugID, 'unlinkedfrombuild', '', $buildID);
}
/**
* Build action menu.
*
* @param object $build
* @param string $type
* @access public
* @return string
*/
public function buildOperateMenu($build, $type = 'view')
{
$canBeChanged = common::canBeChanged('build', $build);
if($build->deleted || !$canBeChanged) return '';
$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');
return $menu;
}
}
+1 -9
View File
@@ -48,15 +48,7 @@ tbody tr td:first-child input {display: none;}
</div>
<?php if(!isonlybody()):?>
<div class='btn-toolbar pull-right'>
<?php
if(!$build->deleted and $canBeChanged)
{
echo $this->buildOperateMenu($build, 'view');
if(common::hasPriv('build', 'edit')) echo html::a($this->createLink('build', 'edit', "buildID=$build->id"), "<i class='icon-common-edit icon-edit'></i> " . $this->lang->edit, '', "class='btn btn-link' title='{$this->lang->edit}' data-app='{$app->tab}'");
if(common::hasPriv('build', 'delete')) echo html::a($this->createLink('build', 'delete', "buildID=$build->id"), "<i class='icon-common-delete icon-trash'></i> " . $this->lang->delete, '', "class='btn btn-link' title='{$this->lang->delete}' target='hiddenwin' data-app='{$app->tab}'");
}
?>
<?php echo $this->build->buildOperateMenu($build, 'view');?>
</div>
<?php endif;?>
</div>
+2 -1
View File
@@ -25,7 +25,8 @@ $lang->caselib->exportTemplet = '导出模板';
$lang->caselib->batchCreateCase = '批量创建用例';
$lang->caselib->import = '导入';
$lang->caselib->showImport = '显示导入数据';
$lang->caselib->type = '类型';
$lang->caselib->product = '所属' . $lang->productCommon;
$lang->caselib->browseAction = '用例库列表';
$lang->caselib->deleteAction = "删除用例库";
$lang->caselib->importAction = '导入用例';
+1 -1
View File
@@ -157,7 +157,7 @@ js::set('flow', $config->global->flow);
<td class='<?php if(isset($run)) echo $run->status;?> testcase-<?php echo $case->status?>'> <?php echo $this->processStatus('testcase', $case);?></td>
<?php foreach($extendFields as $extendField) echo "<td>" . $this->loadModel('flow')->getFieldValue($extendField, $case) . "</td>";?>
<td class='c-actions'>
<?php echo $this->buildOperateMenu($case, 'browse');?>
<?php echo $this->caselib->buildOperateMenu($case, 'browse');?>
</td>
</tr>
<?php endforeach;?>
+1 -1
View File
@@ -39,7 +39,7 @@
<div class="btn-toolbar">
<?php common::printBack($browseLink);?>
<?php echo "<div class='divider'></div>";?>
<?php echo $this->buildOperateMenu($lib, 'view');?>
<?php echo $this->caselib->buildOperateMenu($lib, 'view');?>
</div>
</div>
</div>
+20
View File
@@ -695,6 +695,26 @@ class doc extends control
}
}
/**
* Update order.
*
* @access public
* @return void
*/
public function updateOrder()
{
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
foreach($_POST['orders'] as $id => $order)
{
$this->dao->update(TABLE_DOC)->set('`order`')->eq($order)->where('id')->eq($id)->exec();
}
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success'));
}
}
/**
* Ajax get modules by libID.
*
+18
View File
@@ -20,3 +20,21 @@ span.dotted-line+a {display: block;}
.tree li.has-list.open:before {content: unset;}
#modules i.icon-file-text {color: #D0D2D6; font-size: 14px;}
.tree li>a {max-width: 80%;}
.sortable-sorting .module-name > a {cursor: move;}
.sortable-sorting li >.tree-group {opacity: .5;}
.sortable-sorting .drop-here .tree-group {background-color: #fff3e0;}
.sortable-sorting .drop-here .tree-group > * {opacity: .1;}
.sortable-sorting .drag-shadow .tree-group {opacity: 1!important;}
.sortable-sorting .drag-shadow .tree-actions {visibility: hidden;}
.is-sorting > li > .tree-group {opacity: 1; border-radius: 4px;}
.is-sorting > li ul {display: none!important;}
.tree-group {position: relative;}
.tree-group > .module-name {white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 100%; display: block;}
.tree-group .tree-actions {display: none; position: absolute; right: 0; top: 0; background-color: #fff; white-space: nowrap;}
.tree-group:hover > .module-name {width: calc(100% - 20px);}
.tree-group:hover .tree-actions {display: block}
.tree li.has-list.open:before {left: 6px;}
.sortDoc>.tail-info{right: 20px;}
.sortDoc>.tree-actions{position: absolute; right: 0px; background: #fff;}
+77
View File
@@ -18,4 +18,81 @@ $(function()
})
$('.menu-actions > a').blur(function() {$(this).css('background', 'none');})
/* Make modules tree sortable. */
$('#modules').sortable(
{
trigger: '.module-name>a.sort-module, .tree-actions>.sortModule>.icon-move, a.sortDoc, .tree-actions>.sortDoc>.icon-move',
dropToClass: 'sort-to',
stopPropagation: true,
nested: true,
selector: 'li',
dragCssClass: 'drop-here',
canMoveHere: function($ele, $target)
{
var maxTop = $('.side-col > .cell > ul').height() - $ele.height();
if(parseFloat($('.drag-shadow').css('top')) < 0) $('.drag-shadow').css('top', '0');
if(parseFloat($('.drag-shadow').css('left')) != 0) $('.drag-shadow').css('left', '0');
if(parseFloat($('.drag-shadow').css('top')) > maxTop) $('.drag-shadow').css('top', maxTop + 'px');
return true;
},
targetSelector: function($ele, $root)
{
var $ul = $ele.closest('ul');
setTimeout(function()
{
if($('#modules').hasClass('sortable-sorting')) $ul.addClass('is-sorting');
}, 100);
if($ele.hasClass('sortDoc'))
{
return $ul.children('li.sortDoc');
}
else
{
return $ul.children('li.catalog');
}
},
always: function()
{
$('#modules,#modules .is-sorting').removeClass('is-sorting');
},
finish: function(e)
{
if(!e.changed) return;
var orders = {};
var link = '';
var elementClass = e.list.context.className;
if(elementClass.indexOf('sortDoc') >= 0)
{
$('#modules').find('li.sortDoc').each(function()
{
var $li = $(this);
var item = $li.data();
orders['orders[' + item.id + ']'] = $li.attr('data-order') || item.order;
});
link = createLink('doc', 'updateOrder');
}
else
{
$('#modules').find('li.can-sort').each(function()
{
var $li = $(this);
var item = $li.data();
'<?php echo $type;?>' == 'book' ? orders['sort[' + item.id + ']'] = $li.attr('data-order') || item.order : orders['orders[' + item.id + ']'] = $li.attr('data-order') || item.order;
});
link = createLink('tree', 'updateOrder');
}
$.post(link, orders, function(data){}).error(function()
{
bootbox.alert(lang.timeout);
});
}
});
})
+1
View File
@@ -93,6 +93,7 @@ $lang->doc->collector = 'Collector';
$lang->doc->main = 'Main Document Library';
$lang->doc->order = 'Order';
$lang->doc->doc = 'Document';
$lang->doc->updateOrder = 'Update Order';
$lang->doc->moduleDoc = 'By Module';
$lang->doc->searchDoc = 'Search';
+1
View File
@@ -93,6 +93,7 @@ $lang->doc->collector = '收藏者';
$lang->doc->main = '文档主库';
$lang->doc->order = '排序';
$lang->doc->doc = '文档';
$lang->doc->updateOrder = '更新排序';
$lang->doc->moduleDoc = '按模块浏览';
$lang->doc->searchDoc = '搜索';
+45 -19
View File
@@ -2379,6 +2379,7 @@ EOT;
$docs = $this->dao->select('*')->from(TABLE_DOC)
->where('lib')->eq($rootID)
->andWhere('deleted')->eq(0)
->orderBy('`order` asc')
->fetchAll();
$moduleDocs = array();
foreach($docs as $doc)
@@ -2410,25 +2411,36 @@ EOT;
{
if(!$docID and $currentMethod != 'tablecontents') $docID = $doc->id;
$treeMenu[0] .= '<li' . ($doc->id == $docID ? ' class="active"' : ' class="independent"') . " data-id=$doc->id>";
$class = common::hasPriv('doc', 'updateOrder') ? ' sortDoc' : '';
$treeMenu[0] .= '<li' . " class='" . ($doc->id == $docID ? 'active' : 'doc') . "$class'" . " data-id=$doc->id>";
if($currentMethod == 'tablecontents')
{
$treeMenu[0] .= '<span class="tail-info">' . zget($users, $doc->editedBy) . ' &nbsp;' . $doc->editedDate . '</span>';
$treeMenu[0] .= '<div class="tree-group"><span class="tail-info">' . zget($users, $doc->editedBy) . ' &nbsp;' . $doc->editedDate . '</span>';
if(common::hasPriv('doc', 'updateOrder'))
{
$treeMenu[0] .= "<div class='tree-actions'>";
$treeMenu[0] .= html::a('javascript:;', "<i class='icon icon-move sortDoc'></i>", '', "title='{$this->lang->doc->updateOrder}' class='sortDoc'");
$treeMenu[0] .= '</div>';
}
}
if($currentMethod == 'objectlibs')
{
$treeMenu[0] .= "<div class='tree-group'><span class='module-name'>" . html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$rootID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title' title='{$doc->title}'") . '</span>';
if(common::hasPriv('doc', 'edit'))
$class = common::hasPriv('doc', 'updateOrder') ? 'sortDoc' : '';
$treeMenu[0] .= "<div class='tree-group'><span class='module-name'>" . html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$rootID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title $class' title='{$doc->title}'") . '</span>';
if(common::hasPriv('doc', 'edit') or common::hasPriv('doc', 'updateOrder'))
{
$treeMenu[0] .= "<div class='tree-actions'>";
$treeMenu[0] .= html::a(helper::createLink('doc', 'edit', "docID={$doc->id}&comment=false&objectType=$type&objectID=$objectID&libID=$rootID"), "<i class='icon icon-edit'></i>", '', "title={$this->lang->doc->edit} data-app='{$this->app->tab}'");
if(common::hasPriv('doc', 'edit')) $treeMenu[0] .= html::a(helper::createLink('doc', 'edit', "docID={$doc->id}&comment=false&objectType=$type&objectID=$objectID&libID=$rootID"), "<i class='icon icon-edit'></i>", '', "title={$this->lang->doc->edit} data-app='{$this->app->tab}'");
if(common::hasPriv('doc', 'updateOrder')) $treeMenu[0] .= html::a('javascript:;', "<i class='icon icon-move sortDoc'></i>", '', "title='{$this->lang->doc->updateOrder}' class='sortDoc'");
$treeMenu[0] .= '</div></div>';
}
}
else
{
$treeMenu[0] .= html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$rootID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title' title='{$doc->title}'");
$class = common::hasPriv('doc', 'updateOrder') ? 'sortDoc' : '';
$treeMenu[0] .= html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$rootID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title $class' title='{$doc->title}'");
$treeMenu[0] .= '</div>';
}
$treeMenu[0] .= '</li>';
@@ -2477,27 +2489,38 @@ EOT;
else
{
if(!$docID and $currentMethod != 'tablecontents') $docID = $doc->id;
$treeMenu[$module->id] .= '<li' . ($doc->id == $docID ? ' class="active"' : ' class="doc"') . " data-id=$doc->id>";
$class = common::hasPriv('doc', 'updateOrder') ? ' sortDoc' : '';
$treeMenu[$module->id] .= '<li' . " class='" . ($doc->id == $docID ? 'active' : 'doc') . "$class'" . " data-id=$doc->id>";
if($currentMethod == 'tablecontents')
{
$treeMenu[$module->id] .= '<span class="tail-info">' . zget($users, $doc->editedBy) . ' &nbsp;' . $doc->editedDate . '</span>';
$treeMenu[$module->id] .= '<div class="tree-group"><span class="tail-info">' . zget($users, $doc->editedBy) . ' &nbsp;' . $doc->editedDate . '</span>';
if(common::hasPriv('doc', 'updateOrder'))
{
$treeMenu[$module->id] .= "<div class='tree-actions'>";
$treeMenu[$module->id] .= html::a('javascript:;', "<i class='icon icon-move sortDoc'></i>", '', "title='{$this->lang->doc->updateOrder}' class='sortDoc'");
$treeMenu[$module->id] .= '</div>';
}
}
if($currentMethod == 'objectlibs')
{
$treeMenu[$module->id] .= "<div class='tree-group'><span class='module-name'>" . html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$libID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title' title='{$doc->title}'") . '</span>';
if(common::hasPriv('doc', 'edit'))
$class = common::hasPriv('doc', 'updateOrder') ? 'sortDoc' : '';
$treeMenu[$module->id] .= "<div class='tree-group'><span class='module-name'>" . html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$libID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title $class' title='{$doc->title}'") . '</span>';
if(common::hasPriv('doc', 'edit') or common::hasPriv('doc', 'updateOrder'))
{
$treeMenu[$module->id] .= "<div class='tree-actions'>";
$treeMenu[$module->id] .= html::a(helper::createLink('doc', 'edit', "docID={$doc->id}&comment=false&objectType=$type&objectID=$objectID&libID=$libID"), "<i class='icon icon-edit'></i>", '', "title={$this->lang->doc->edit} data-app={$this->app->tab}");
if(common::hasPriv('doc', 'edit')) $treeMenu[$module->id] .= html::a(helper::createLink('doc', 'edit', "docID={$doc->id}&comment=false&objectType=$type&objectID=$objectID&libID=$libID"), "<i class='icon icon-edit'></i>", '', "title={$this->lang->doc->edit} data-app={$this->app->tab}");
if(common::hasPriv('doc', 'updateOrder')) $treeMenu[$module->id] .= html::a('javascript:;', "<i class='icon icon-move sortDoc'></i>", '', "title='{$this->lang->doc->updateOrder}' class='sortDoc'");
$treeMenu[$module->id] .= '</div>';
}
$treeMenu[$module->id] .= '</div>';
}
elseif($currentMethod == 'tablecontents')
{
$treeMenu[$module->id] .= html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$libID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title' title='{$doc->title}'");
$class = common::hasPriv('doc', 'updateOrder') ? 'sortDoc' : '';
$treeMenu[$module->id] .= html::a(inlink('objectLibs', "type=$type&objectID=$objectID&libID=$libID&docID={$doc->id}"), "<i class='icon icon-file-text text-muted'></i> &nbsp;" . $doc->title, '', "data-app='{$this->app->tab}' class='doc-title $class' title='{$doc->title}'");
$treeMenu[$module->id] .= '</div>';
}
$treeMenu[$module->id] .= '</li>';
@@ -2511,22 +2534,25 @@ EOT;
}
else
{
if($currentMethod == 'tablecontents')
$li = "<div class='tree-group'><span class='module-name'><a class='sort-module' title='{$module->name}'>" . $module->name . '</a></span>';
if($currentMethod == 'tablecontents' and common::hasPriv('tree', 'updateOrder'))
{
$li = "<a title='{$module->name}'>" . $module->name . '</a>';
$li .= "<div class='tree-actions'>";
$li .= html::a('javascript:;', "<i class='icon icon-move sortModule'></i>", '', "title='{$this->lang->doc->updateOrder}' class='sortModule'");
$li .= '</div>';
}
else
{
$li = "<div class='tree-group'><span class='module-name'><a class='sort-module' title='{$module->name}'>" . $module->name . '</a></span>';
if(common::hasPriv('tree', 'edit') or common::hasPriv('tree', 'browse'))
if(common::hasPriv('tree', 'edit') or common::hasPriv('tree', 'browse') or common::hasPriv('tree', 'browse') or common::hasPriv('tree', 'updateOrder'))
{
$li .= "<div class='tree-actions'>";
if(common::hasPriv('tree', 'edit')) $li .= html::a(helper::createLink('tree', 'edit', "module=$module->id&type=doc"), "<i class='icon icon-edit'></i>", '', "data-toggle='modal' title={$this->lang->doc->editType}");
if(common::hasPriv('tree', 'browse')) $li .= html::a(helper::createLink('tree', 'browse', "rootID=$libID&type=doc&module=$module->id", '', 1), "<i class='icon icon-split'></i>", '', "class='iframe' title={$this->lang->doc->editChildType}");
if(common::hasPriv('tree', 'edit')) $li .= html::a(helper::createLink('tree', 'edit', "module=$module->id&type=doc"), "<i class='icon icon-edit'></i>", '', "data-toggle='modal' title='{$this->lang->doc->editType}'");
if(common::hasPriv('tree', 'browse')) $li .= html::a(helper::createLink('tree', 'browse', "rootID=$libID&type=doc&module=$module->id", '', 1), "<i class='icon icon-split'></i>", '', "class='iframe' title='{$this->lang->doc->editChildType}'");
if(common::hasPriv('tree', 'updateOrder')) $li .= html::a('javascript:;', "<i class='icon icon-move sortModule'></i>", '', "title='{$this->lang->doc->updateOrder}' class='sortModule'");
$li .= '</div>';
}
$li .= '</div>';
}
$li .= '</div>';
}
if($treeMenu[$module->id])
{
+35 -9
View File
@@ -79,7 +79,7 @@ $sideWidth = common::checkNotCN() ? '270' : '238';
/* Make modules tree sortable */
$('#modules').sortable(
{
trigger: '.module-name>a.sort-module',
trigger: '.module-name>a.sort-module, .tree-actions>.sortModule>.icon-move, .module-name>a.sortDoc, .tree-actions>.sortDoc>.icon-move',
dropToClass: 'sort-to',
stopPropagation: true,
nested: true,
@@ -100,7 +100,15 @@ $sideWidth = common::checkNotCN() ? '270' : '238';
{
if($('#modules').hasClass('sortable-sorting')) $ul.addClass('is-sorting');
}, 100);
return $ul.children('li');
if($ele.hasClass('sortDoc'))
{
return $ul.children('li.sortDoc');
}
else
{
return $ul.children('li.catalog');
}
},
always: function()
{
@@ -110,16 +118,34 @@ $sideWidth = common::checkNotCN() ? '270' : '238';
{
if(!e.changed) return;
var orders = {};
$('#modules').find('li.can-sort').each(function()
var orders = {};
var link = '';
var elementClass = e.list.context.className;
if(elementClass.indexOf('sortDoc') >= 0)
{
var $li = $(this);
$('#modules').find('li.sortDoc').each(function()
{
var $li = $(this);
var item = $li.data();
'<?php echo $type;?>' == 'book' ? orders['sort[' + item.id + ']'] = $li.attr('data-order') || item.order : orders['orders[' + item.id + ']'] = $li.attr('data-order') || item.order;
});
var item = $li.data();
orders['orders[' + item.id + ']'] = $li.attr('data-order') || item.order;
});
link = createLink('doc', 'updateOrder');
}
else
{
$('#modules').find('li.can-sort').each(function()
{
var $li = $(this);
var item = $li.data();
'<?php echo $type;?>' == 'book' ? orders['sort[' + item.id + ']'] = $li.attr('data-order') || item.order : orders['orders[' + item.id + ']'] = $li.attr('data-order') || item.order;
});
link = '<?php echo $type?>' == 'book' ? createLink('doc', 'sortBookOrder') : createLink('tree', 'updateOrder');
}
var link = '<?php echo $type;?>' == 'book' ? createLink('doc', 'sortBookOrder') : createLink('tree', 'updateOrder');
$.post(link, orders, function(data){}).error(function()
{
bootbox.alert(lang.timeout);
+9 -3
View File
@@ -1677,9 +1677,15 @@ class execution extends control
if($this->app->tab == 'project')
{
$projectID = $this->session->project;
$projectID = $this->session->project;
$project = $this->project->getById($projectID);
$allProjects = $this->project->getPairsByModel($project->model, 0, 'noclosed', isset($projectID) ? $projectID : 0);
$this->project->setMenu($projectID);
$this->view->project = $this->project->getById($projectID);
$this->view->project = $project;
}
else
{
$allProjects = $this->project->getPairsByModel('all', 0, 'noclosed', isset($projectID) ? $projectID : 0);
}
if(!$this->post->executionIDList) return print(js::locate($this->session->executionList, 'parent'));
@@ -1717,7 +1723,7 @@ class execution extends control
$this->view->position[] = $this->lang->execution->batchEdit;
$this->view->executionIDList = $executionIDList;
$this->view->executions = $executions;
$this->view->allProjects = $this->project->getPairsByModel('all', 0, 'noclosed', isset($projectID) ? $projectID : 0);
$this->view->allProjects = $allProjects;
$this->view->pmUsers = $pmUsers;
$this->view->poUsers = $poUsers;
$this->view->qdUsers = $qdUsers;
+12 -11
View File
@@ -1,13 +1,14 @@
$(function()
function changeProject(obj, executionID, projectID)
{
$('[id^="projects"]').change(function()
var $td = $(obj).closest('td');
if($td.find('[id^="syncStories"]').length == 0)
{
var executionID = $(this).attr('id').replace('projects', '');
var $td = $(this).closest('td');
if($td.find('[id^="syncStories"]').length == 0)
{
$td.append("<input type='hidden' id='syncStories" + executionID + "' name='syncStories[" + executionID + "]' value='no' />");
}
$("#syncStories" + executionID).val(confirm(confirmSyncStories) ? 'yes' : 'no');
})
});
$td.append("<input type='hidden' id='syncStories" + executionID + "' name='syncStories[" + executionID + "]' value='no' />");
}
var confirmVal = confirm(confirmSync);
$("#syncStories" + executionID).val(confirmVal ? 'yes' : 'no');
if(!confirmVal)
{
$(obj).val(projectID).trigger("chosen:updated");
}
};
+1 -1
View File
@@ -71,6 +71,6 @@ $(function()
{
$('#submit').after("<input type='hidden' id='syncStories' name='syncStories' value='no' />");
}
$("#syncStories").val(confirm(confirmSyncStories) ? 'yes' : 'no');
$("#syncStories").val(confirm(confirmSync) ? 'yes' : 'no');
});
})
+1 -1
View File
@@ -340,7 +340,7 @@ if($config->systemMode == 'new') $lang->execution->copyTeamTitle = "Choose a
$lang->execution->confirmDelete = "Do you want to delete the {$lang->executionCommon}[%s]?";
$lang->execution->confirmUnlinkMember = "Do you want to unlink this User from {$lang->executionCommon}?";
$lang->execution->confirmUnlinkStory = "After {$lang->SRCommon} is removed, cased linked to {$lang->SRCommon} will be reomoved and tasks linked to {$lang->SRCommon} will be cancelled. Do you want to continue?";
$lang->execution->confirmSyncStories = "After modifying the project, synchronize the execution related {$lang->SRCommon} to the new project?";
$lang->execution->confirmSync = "After modifying the project, in order to maintain the consistency of data, the data of products, requirements, teams and whitelist associated with the implementation will be synchronized to the new project. Please know.";
$lang->execution->confirmUnlinkExecutionStory = "Do you want to unlink this Story from the execution?";
$lang->execution->notAllowedUnlinkStory = "This {$lang->SRCommon} is linked to the {$lang->executionCommon} of the execution. Remove it from the {$lang->executionCommon}, then try again.";
$lang->execution->notAllowRemoveProducts = "The story of this product is linked with the {$lang->executionCommon}. Unlink it before doing any action.";
+1 -1
View File
@@ -340,7 +340,7 @@ if($config->systemMode == 'new') $lang->execution->copyTeamTitle = "选择
$lang->execution->confirmDelete = "您确定删除{$lang->executionCommon}[%s]吗?";
$lang->execution->confirmUnlinkMember = "您确定从该{$lang->executionCommon}中移除该用户吗?";
$lang->execution->confirmUnlinkStory = "移除该{$lang->SRCommon}后,该{$lang->SRCommon}关联的用例将被移除,该{$lang->SRCommon}关联的任务将被取消,请确认。";
$lang->execution->confirmSyncStories = "修改所属项目后执行关联的{$lang->SRCommon}是否同步到新项目中";
$lang->execution->confirmSync = "修改所属项目后,为了保持数据的一致性,该执行关联的产品、需求、团队和白名单数据将会同步到新项目中,请知悉。";
$lang->execution->confirmUnlinkExecutionStory = "您确定从该项目中移除该{$lang->SRCommon}吗?";
$lang->execution->notAllowedUnlinkStory = "{$lang->SRCommon}已经与项目下{$lang->executionCommon}相关联,请从{$lang->executionCommon}中移除后再操作。";
$lang->execution->notAllowRemoveProducts = "{$lang->productCommon}中的{$lang->SRCommon}已与该{$lang->executionCommon}进行了关联,请取消关联后再操作。";
+115 -5
View File
@@ -684,6 +684,27 @@ class executionModel extends model
$projectID = isset($execution->project) ? $execution->project : $oldExecution->project;
$project = $this->project->getByID($projectID);
if(isset($execution->project))
{
$executionProductList = $this->loadModel('product')->getProducts($executionID);
$projectProductList = $this->product->getProducts($execution->project);
$executionProductIdList = array_keys($executionProductList);
$projectProductIdList = array_keys($projectProductList);
$diffProductIdList = array_diff($executionProductIdList, $projectProductIdList);
if(!empty($diffProductIdList))
{
foreach($diffProductIdList as $key => $newProductID)
{
$data = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)
->where('project')->eq($executionID)
->andWhere('product')->eq($newProductID)
->fetch();
$data->project = $execution->project;
$this->dao->insert(TABLE_PROJECTPRODUCT)->data($data)->exec();
}
}
}
if($project and $execution->begin < $project->begin)
{
dao::$errors['begin'] = sprintf($this->lang->execution->errorLetterProject, $project->begin);
@@ -2791,15 +2812,70 @@ class executionModel extends model
public function computeBurn()
{
$today = helper::today();
$burns = array();
$executions = $this->dao->select('id, code')->from(TABLE_EXECUTION)
->where('end')->ge($today)
->andWhere('type')->ne('ops')
->andWhere('type')->in('sprint,stage')
->andWhere('lifetime')->ne('ops')
->andWhere('status')->notin('done,closed,suspended')
->fetchPairs();
if(!$executions) return $burns;
if(!$executions) return array();
/* Update historical data of burn. */
$table = $this->config->edition == 'open' ? TABLE_TASKESTIMATE : TABLE_EFFORT;
$field = $this->config->edition == 'open' ? 'task' : 'objectID';
$totalConsumed = $this->dao->select("t2.execution as execution, t1.$field as task, t1.date as date, sum(t1.consumed) as totalConsumed")->from($table)->alias('t1')
->leftJoin(TABLE_TASK)->alias('t2')->on("t1.$field=t2.id")
->where('t2.execution')->in(array_keys($executions))
->beginIF($this->config->edition != 'open')->andWhere('t1.objectType')->eq('task')->fi()
->andWhere('t2.deleted')->eq('0')
->andWhere('t2.parent')->ge('0')
->andWhere('t2.status')->ne('cancel')
->andWhere('t1.date')->ne($today)
->groupBy("t1.$field, t1.date")
->orderBy('t1.id_desc')
->fetchGroup('task', 'date');
$latestIdList = $this->dao->select('max(id) as id')->from($table)
->where($field)->in(array_keys($totalConsumed))
->beginIF($this->config->edition != 'open')->andWhere('objectType')->eq('task')->fi()
->groupBy("$field,date")->fetchAll('id');
$latestLefts = $this->dao->select("$field, date, `left`")->from($table)
->where('id')->in(array_keys($latestIdList))
->fetchGroup($field, 'date');
$burnList = array();
foreach($totalConsumed as $taskID => $consumedList)
{
foreach($consumedList as $date => $consumed)
{
$executionID = $consumed->execution;
if(!isset($burnList[$executionID])) $burnList[$executionID] = array();
if(!isset($burnList[$executionID][$date]))
{
$burnList[$executionID][$date] = new stdclass();
$burnList[$executionID][$date]->consumed = 0;
$burnList[$executionID][$date]->left = 0;
}
$burnList[$executionID][$date]->consumed += $consumed->totalConsumed;
$burnList[$executionID][$date]->left += $latestLefts[$taskID][$date]->left;
}
}
foreach($burnList as $executionID => $burns)
{
foreach($burns as $date => $burn)
{
$burn->execution = $executionID;
$burn->date = $date;
$this->dao->replace(TABLE_BURN)->data($burn)->exec();
$burn->executionName = $executions[$burn->execution];
}
}
/* Update today's data of burn. */
$burns = $this->dao->select("execution, '$today' AS date, sum(estimate) AS `estimate`, sum(`left`) AS `left`, SUM(consumed) AS `consumed`")
->from(TABLE_TASK)
->where('execution')->in(array_keys($executions))
@@ -2852,8 +2928,10 @@ class executionModel extends model
$this->dao->replace(TABLE_BURN)->data($burn)->exec();
$burn->executionName = $executions[$burn->execution];
$burnList[$executionID][$today] = $burn;
}
return $burns;
return $burnList;
}
/**
@@ -3955,4 +4033,36 @@ class executionModel extends model
}
$this->dao->update(TABLE_PROJECT)->set('path')->eq($path['path'])->set('grade')->eq($path['grade'])->where('id')->eq($execution->id)->exec();
}
/**
* Build execution action menu.
*
* @param object $execution
* @param string $type
* @access public
* @return string
*/
public function buildOperateMenu($execution, $type = 'view')
{
if($execution->deleted) return '';
$menu = '';
$params = "executionID=$execution->id";
$menu .= "<div class='divider'></div>";
$menu .= $this->buildMenu('execution', 'start', $params, $execution, $type, '', '', 'iframe', true);
$menu .= $this->buildMenu('execution', 'activate', $params, $execution, $type, '', '', 'iframe', true);
$menu .= $this->buildMenu('execution', 'putoff', $params, $execution, $type, '', '', 'iframe', true);
$menu .= $this->buildMenu('execution', 'suspend', $params, $execution, $type, '', '', 'iframe', true);
$menu .= $this->buildMenu('execution', 'close', $params, $execution, $type, '', '', 'iframe', true);
$menu .= "<div class='divider'></div>";
$menu .= $this->buildFlowMenu('execution', $execution, 'view', 'direct');
$menu .= "<div class='divider'></div>";
$menu .= $this->buildMenu('execution', 'edit', "execution=$execution->id", $execution);
$menu .= $this->buildMenu('execution', 'delete', "execution=$execution->id", $execution, 'button', 'trash', 'hiddenwin');
return $menu;
}
}
+2 -2
View File
@@ -83,7 +83,7 @@
<tr>
<td><?php echo sprintf('%03d', $executionID) . html::hidden("executionIDList[$executionID]", $executionID);?></td>
<?php if($config->systemMode == 'new' and isset($project) and $project->model == 'scrum'):?>
<td class='text-left' style='overflow:visible'><?php echo html::select("projects[$executionID]", $allProjects, $executions[$executionID]->project, "class='form-control picker-select'");?></td>
<td class='text-left' style='overflow:visible'><?php echo html::select("projects[$executionID]", $allProjects, $executions[$executionID]->project, "class='form-control picker-select' onchange='changeProject(this, $executionID, {$executions[$executionID]->project})'");?></td>
<?php endif;?>
<td title='<?php echo $executions[$executionID]->name?>'><?php echo html::input("names[$executionID]", $executions[$executionID]->name, "class='form-control'");?></td>
<td><?php echo html::input("codes[$executionID]", $executions[$executionID]->code, "class='form-control'");?></td>
@@ -137,5 +137,5 @@
</form>
</div>
<?php js::set('weekend', $config->execution->weekend);?>
<?php js::set('confirmSyncStories', $lang->execution->confirmSyncStories);?>
<?php js::set('confirmSync', $lang->execution->confirmSync);?>
<?php include '../../common/view/footer.html.php';?>
+5 -2
View File
@@ -11,8 +11,11 @@
*/
?>
<?php
foreach($burns as $burn)
foreach($burns as $executionID => $burnList)
{
echo $burn->execution . "\t" . $burn->executionName . "\t" . $burn->date . "\t" . $burn->left . "\n";
foreach($burnList as $date => $burn)
{
echo $burn->execution . "\t" . $burn->executionName . "\t" . $burn->date . "\t" . $burn->left . "\n";
}
}
?>
+1 -1
View File
@@ -220,6 +220,6 @@
<?php js::set('unmodifiableBranches', $unmodifiableBranches)?>
<?php js::set('multiBranchProducts', $multiBranchProducts);?>
<?php js::set('tip', $lang->execution->notAllowRemoveProducts);?>
<?php js::set('confirmSyncStories', $lang->execution->confirmSyncStories);?>
<?php js::set('confirmSync', $lang->execution->confirmSync);?>
<?php js::set('systemMode', $config->systemMode);?>
<?php include '../../common/view/footer.html.php';?>
+3 -20
View File
@@ -146,26 +146,9 @@
</div>
<div class='main-actions'>
<div class="btn-toolbar">
<?php
$params = "execution=$execution->id";
$browseLink = $this->session->executionList ? $this->session->executionList : inlink('browse', "executionID=$execution->id");
common::printBack($browseLink);
if(!$execution->deleted)
{
echo "<div class='divider'></div>";
common::printIcon('execution', 'start', "executionID=$execution->id", $execution, 'button', '', '', 'iframe', true);
common::printIcon('execution', 'activate', "executionID=$execution->id", $execution, 'button', '', '', 'iframe', true);
common::printIcon('execution', 'putoff', "executionID=$execution->id", $execution, 'button', '', '', 'iframe', true);
common::printIcon('execution', 'suspend', "executionID=$execution->id", $execution, 'button', '', '', 'iframe', true);
common::printIcon('execution', 'close', "executionID=$execution->id", $execution, 'button', '', '', 'iframe', true);
echo $this->buildOperateMenu($execution, 'view');
echo "<div class='divider'></div>";
common::printIcon('execution', 'edit', $params, $execution);
common::printIcon('execution', 'delete', $params, $execution, 'button', 'trash', 'hiddenwin');
}
?>
<?php $browseLink = $this->session->executionList ? $this->session->executionList : inlink('browse', "executionID=$execution->id");?>
<?php common::printBack($browseLink);?>
<?php echo $this->execution->buildOperateMenu($execution, 'view');?>
</div>
</div>
</div>
+1 -1
View File
@@ -259,7 +259,7 @@ class gitlab extends control
$user = $this->gitlab->apiGetCurrentUser($gitlab->url, $gitlab->token, true);
if(!is_object($user)) return $this->send(array('result' => 'fail', 'message' => array('url' => array(sprintf($this->lang->gitlab->hostError, $this->config->gitlab->minCompatibleVersion)))));
if(isset($user->error)) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->gitlab->tokenError))));
if(!isset($user->id)) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->gitlab->tokenError))));
/* Verify version compatibility. */
$result = $this->gitlab->getVersion($gitlab->url, $gitlab->token);
+1
View File
@@ -1215,6 +1215,7 @@ $lang->resource->doc->objectLibs = 'objectLibs';
$lang->resource->doc->collect = 'collectAction';
$lang->resource->doc->tableContents = 'tableContents';
$lang->resource->doc->showFiles = 'showFiles';
$lang->resource->doc->updateOrder = 'updateOrder';
$lang->doc->methodOrder[0] = 'index';
$lang->doc->methodOrder[5] = 'browse';
+53 -31
View File
@@ -19,6 +19,7 @@
#archivedCards .kanban-item > .info {margin-top: 5px; position: relative;}
#archivedCards .kanban-item > .info > .pri {height: 14px; border-width: 1px; font-size: 12px; line-height: 12px; min-width: 14px; padding: 0 1px;}
#archivedCards .kanban-item > .info > .time {margin-left: 10px; font-size: 12px}
#archivedCards .kanban-item > .info.build > .time {margin-left:0px; font-size: 12px}
#archivedCards .kanban-item > .info > .user {position: absolute; right: 0; top: 0}
#archivedCards .card-actions {position: relative; padding: 15px 10px; padding-top: 0px;}
#archivedCards .card-actions > .btn {display: block;}
@@ -41,7 +42,9 @@
#archivedCards .card-item .has-color .info > .label-pri,
#archivedCards .card-item .has-color .info > .estimate,
#archivedCards .card-item .has-color .info > .label-light {color: #FFFFFF;}
#archivedCards .info.execution .label-light, #archivedCards .info.productplan .label-light, #archivedCards .info.build .label-light, #archivedCards .info.release .label-light {background: #EFEFEF !important; color: #838A9D !important;}
#archivedCards .card-item .has-color .info > .label-pri {border-color: #FFFFFF;}
#archivedCards .card-item .has-color .progress-box > .progress-number {color: #FFFFFF;}
#archivedCards .progress-box {width: 97%;}
#performable {padding: 25px 10px !important;}
</style>
@@ -91,51 +94,70 @@ $app->loadLang('productplan');
<?php else:?>
<?php
$name = isset($card->title) ? $card->title : $card->name;
if(common::hasPriv($card->fromType, 'view')) echo html::a($this->createLink('productplan', 'view', "id=$card->fromID"), $name, '', "class='cardName' title='$name'");
if(common::hasPriv($card->fromType, 'view')) echo html::a($this->createLink($card->fromType, 'view', "id=$card->fromID"), $name, '', "class='cardName' title='$name'");
if(!common::hasPriv($card->fromType, 'view')) echo "<div class='cardName' title='$name'>$name</div>";
echo "<div class='info $card->fromType'>";
if($card->fromType != 'release' and isset($lang->{$card->fromType}->statusList[$card->objectStatus])) echo "<span class='label label-$card->objectStatus'>" . $lang->{$card->fromType}->statusList[$card->objectStatus] . '</span>';
if(isset($card->date) and !helper::isZeroDate($card->date)) echo "<span class='time label label-light'>" . date("m/d", strtotime($card->date)) . "</span>"
if(isset($lang->{$card->fromType}->statusList[$card->objectStatus])) echo "<span class='label label-$card->objectStatus'>" . $lang->{$card->fromType}->statusList[$card->objectStatus] . '</span>';
if(isset($card->date) and !helper::isZeroDate($card->date)) echo "<span class='time label label-light'>" . date("Y-m-d", strtotime($card->date)) . "</span>"
?>
<?php endif;?>
<?php if(helper::isZeroDate($card->end) and !helper::isZeroDate($card->begin)):?>
<?php if(helper::isZeroDate($card->end) and !helper::isZeroDate($card->begin) and $card->begin != '2030-01-01' and $card->end != '2030-01-01'):?>
<span class="time label label-light"><?php echo date("m/d", strtotime($card->begin)) . $lang->kanbancard->beginAB;?></span>
<?php endif;?>
<?php if(helper::isZeroDate($card->begin) and !helper::isZeroDate($card->end)):?>
<?php if(helper::isZeroDate($card->begin) and !helper::isZeroDate($card->end) and $card->begin != '2030-01-01' and $card->end != '2030-01-01'):?>
<span class="time label label-light"><?php echo date("m/d", strtotime($card->end)) . $lang->kanbancard->deadlineAB;?></span>
<?php endif;?>
<?php if(!helper::isZeroDate($card->begin) and !helper::isZeroDate($card->end)):?>
<?php if(!helper::isZeroDate($card->begin) and !helper::isZeroDate($card->end) and $card->begin != '2030-01-01' and $card->end != '2030-01-01' and $card->fromType == ''):?>
<span class="time label label-light"><?php echo date("m/d", strtotime($card->begin)) . ' ~ ' . date("m/d", strtotime($card->end));?></span>
<?php endif;?>
<?php if(!helper::isZeroDate($card->begin) and !helper::isZeroDate($card->end) and $card->begin != '2030-01-01' and $card->end != '2030-01-01' and $card->fromType != ''):?>
<span class="time label label-light"><?php echo date("m-d", strtotime($card->begin)) . ' ' . $lang->{$card->fromType}->to . ' ' . date("m-d", strtotime($card->end));?></span>
<?php endif;?>
<?php
$assignedToList = explode(',', $card->assignedTo);
if($card->begin == '2030-01-01' or $card->end == '2030-01-01') echo '<span class="date label label-future" title="' . $lang->{$card->fromType}->future . '">' . $lang->{$card->fromType}->future . '</span>';
if($card->fromType == '') $assignedToList = explode(',', $card->assignedTo);
if($card->fromType == 'execution') $assignedToList = $card->PM;
if($card->fromType == 'build') $assignedToList = $card->builder;
if($card->fromType == 'release' or $card->fromType == 'productplan') $assignedToList = $card->createdBy;
$count = 0;
$members = '';
?>
<?php
foreach($assignedToList as $index => $account)
{
if(!isset($users[$account]) or !isset($usersAvatar[$account]))
{
unset($assignedToList[$index]);
continue;
}
$members .= $users[$account] . ',';
}
$userCount = count($assignedToList);
?>
<?php if($userCount > 0):?>
<div class='users pull-right' title="<?php echo trim($members, ',');?>">
<?php
foreach($assignedToList as $account)
{
if($count > 2) continue;
echo html::smallAvatar(array('avatar' => $usersAvatar[$account], 'account' => $account, 'name' => $users[$account]), 'avatar-circle');
$count ++;
}
?>
<?php if($count > 2) echo "<span>...</span>";?>
</div>
<?php if(is_array($assignedToList)):?>
<?php
foreach($assignedToList as $index => $account)
{
if(!isset($users[$account]) or !isset($usersAvatar[$account]))
{
unset($assignedToList[$index]);
continue;
}
$members .= $users[$account] . ',';
}
$userCount = count($assignedToList);
?>
<?php if($userCount > 0):?>
<div class='users pull-right' title="<?php echo trim($members, ',');?>">
<?php
foreach($assignedToList as $account)
{
if($count > 2) continue;
echo html::smallAvatar(array('avatar' => $usersAvatar[$account], 'account' => $account, 'name' => $users[$account]), 'avatar-circle');
$count ++;
}
?>
<?php if($count > 2) echo "<span>...</span>";?>
</div>
<?php endif;?>
<?php else:?>
<?php
if(isset($usersAvatar[$assignedToList]) and isset($users[$assignedToList]))
{
echo "<div class='users pull-right' title='" . $users[$assignedToList] . "'>";
echo html::smallAvatar(array('avatar' => $usersAvatar[$assignedToList], 'account' => $assignedToList, 'name' => $users[$assignedToList]), 'avatar-circle');
echo "</div>";
}
?>
<?php endif;?>
</div>
<?php if($kanban->performable):?>
+30
View File
@@ -87,6 +87,36 @@ $config->product->search['params']['closedDate'] = array('operator' => '=',
$config->product->search['params']['lastEditedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->product->search['params']['activatedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->product->all = new stdclass();
$config->product->all->search['module'] = 'product';
$config->product->all->search['fields']['name'] = $lang->product->name;
$config->product->all->search['fields']['code'] = $lang->product->code;
$config->product->all->search['fields']['id'] = $lang->product->id;
if($config->systemMode == 'new') $config->product->all->search['fields']['program'] = $lang->product->program;
$config->product->all->search['fields']['line'] = $lang->product->line;
$config->product->all->search['fields']['desc'] = $lang->product->desc;
$config->product->all->search['fields']['PO'] = $lang->product->PO;
$config->product->all->search['fields']['QD'] = $lang->product->QD;
$config->product->all->search['fields']['RD'] = $lang->product->RD;
$config->product->all->search['fields']['reviewer'] = $lang->product->reviewer;
$config->product->all->search['fields']['type'] = $lang->product->type;
$config->product->all->search['fields']['createdDate'] = $lang->product->createdDate;
$config->product->all->search['fields']['createdBy'] = $lang->product->createdBy;
$config->product->all->search['params']['name'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
$config->product->all->search['params']['code'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
$config->product->all->search['params']['id'] = array('operator' => '=', 'control' => 'input', 'values' => '');
if($config->systemMode == 'new') $config->product->all->search['params']['program'] = array('operator' => '=', 'control' => 'select', 'values' => '');
$config->product->all->search['params']['line'] = array('operator' => '=', 'control' => 'select', 'values' => '');
$config->product->all->search['params']['desc'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
$config->product->all->search['params']['PO'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->product->all->search['params']['QD'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->product->all->search['params']['RD'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->product->all->search['params']['reviewer'] = array('operator' => 'include', 'control' => 'select', 'values' => 'users');
$config->product->all->search['params']['type'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->product->typeList);
$config->product->all->search['params']['createdDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->product->all->search['params']['createdBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->product->create = new stdclass();
$config->product->edit = new stdclass();
$config->product->create->requiredFields = 'name,code';
+11 -2
View File
@@ -1197,22 +1197,30 @@ class product extends control
* @access public
* @return void
*/
public function all($browseType = 'noclosed', $orderBy = 'order_asc')
public function all($browseType = 'noclosed', $orderBy = 'program_asc', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
/* Load module and set session. */
$this->loadModel('program');
$this->session->set('productList', $this->app->getURI(true), 'product');
$queryID = ($browseType == 'bySearch') ? (int)$param : 0;
if($this->app->viewType == 'mhtml')
{
$productID = $this->product->saveState(0, $this->products);
$this->product->setMenu($productID);
}
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Process product structure. */
$productStats = $this->product->getStats($orderBy, '', $browseType, '', 'story');
$productStats = $this->product->getStats($orderBy, $pager, $browseType, '', 'story', '', $queryID);
$productStructure = $this->product->statisticProgram($productStats);
$actionURL = $this->createLink('product', 'all', "browseType=bySearch&orderBy=order_asc&queryID=myQueryID");
$this->product->buildProductSearchForm($param, $actionURL);
$this->view->title = $this->lang->product->common;
$this->view->position[] = $this->lang->product->common;
@@ -1221,6 +1229,7 @@ class product extends control
$this->view->productStructure = $productStructure;
$this->view->orderBy = $orderBy;
$this->view->browseType = $browseType;
$this->view->pager = $pager;
$this->display();
}
+70 -3
View File
@@ -275,6 +275,48 @@ class productModel extends model
->fetchAll('id');
}
/**
* Get list by search.
*
* @param int $queryID
* @access public
* @return array
*/
public function getListBySearch($queryID = 0)
{
if($queryID)
{
$query = $this->loadModel('search')->getQuery($queryID);
if($query)
{
$this->session->set('productQuery', $query->sql);
$this->session->set('productForm', $query->form);
}
else
{
$this->session->set('productQuery', ' 1 = 1');
}
}
else
{
if($this->session->productQuery == false) $this->session->set('productQuery', ' 1 = 1');
}
$productQuery = $this->session->productQuery;
$productQuery = preg_replace('/`(\w+)`/', 't1.`$1`', $productQuery);
$products = $this->dao->select('t1.id as id,t1.*')->from(TABLE_PRODUCT)->alias('t1')
->leftJoin(TABLE_PROGRAM)->alias('t2')->on('t1.program = t2.id')
->where($productQuery)
->andWhere('t1.deleted')->eq(0)
->beginIF(!$this->app->user->admin)->andWhere('t1.id')->in($this->app->user->view->products)->fi()
->andWhere('t1.vision')->eq($this->config->vision)->fi()
->orderBy('t1.order_asc')
->fetchAll('id');
return $products;
}
/**
* Get product pairs.
*
@@ -1049,6 +1091,31 @@ class productModel extends model
$this->loadModel('search')->setSearchParams($this->config->product->search);
}
/**
* Build search form for all method of product module.
*
* @param int $queryID
* @param string $actionURL
* @access public
* @return void
*/
public function buildProductSearchForm($queryID, $actionURL)
{
$this->config->product->all->search['queryID'] = $queryID;
$this->config->product->all->search['actionURL'] = $actionURL;
$linePairs = $this->getLinePairs();
$this->config->product->all->search['params']['line']['values'] = array('' => '') + $linePairs;
if($this->config->systemMode == 'new')
{
$programPairs = $this->loadModel('program')->getTopPairs('', 'noclosed');
$this->config->product->all->search['params']['program']['values'] = array('' => '') + $programPairs;
}
$this->loadModel('search')->setSearchParams($this->config->product->all->search);
}
/**
* Get project pairs by product.
*
@@ -1569,13 +1636,13 @@ class productModel extends model
* @access public
* @return array
*/
public function getStats($orderBy = 'order_asc', $pager = null, $status = 'noclosed', $line = 0, $storyType = 'story', $programID = 0)
public function getStats($orderBy = 'order_asc', $pager = null, $status = 'noclosed', $line = 0, $storyType = 'story', $programID = 0, $param = 0)
{
$this->loadModel('report');
$this->loadModel('story');
$this->loadModel('bug');
$products = $this->getList($programID, $status, $limit = 0, $line);
$products = $status == 'bySearch' ? $this->getListBySearch($param) : $this->getList($programID, $status, $limit = 0, $line);
if(empty($products)) return array();
$productKeys = array_keys($products);
@@ -2043,7 +2110,7 @@ class productModel extends model
$menu .= $this->buildFlowMenu('product', $product, $type, 'direct');
$menu .= "<div class='divider'></div>";
$menu .= $this->buildMenu('product', 'close', $params, $product, $type, '', '', '', '', "data-app='product'");
$menu .= $this->buildMenu('product', 'close', $params, $product, $type, '', '', 'iframe', true, "data-app='product'");
$menu .= "<div class='divider'></div>";
}
+7 -3
View File
@@ -17,6 +17,7 @@
<?php $recTotalLabel = $browseType == $key ? " <span class='label label-light label-badge'>{$recTotal}</span>" : '';?>
<?php echo html::a(inlink("all", "browseType=$key&orderBy=$orderBy"), "<span class='text'>{$label}</span>" . $recTotalLabel, '', "class='btn btn-link' id='{$key}Tab'");?>
<?php endforeach;?>
<a class="btn btn-link querybox-toggle" id='bysearchTab'><i class="icon icon-search muted"></i> <?php echo $lang->product->searchStory;?></a>
</div>
<div class="btn-toolbar pull-right">
<?php common::printLink('product', 'export', "status=$browseType&orderBy=$orderBy", "<i class='icon-export muted'> </i>" . $lang->export, '', "class='btn btn-link export'", true, true)?>
@@ -26,11 +27,13 @@
</div>
<div id="mainContent" class="main-row fade">
<?php if(empty($productStructure)):?>
<div class="cell<?php if($browseType == 'bySearch') echo ' show';?>" id="queryBox" data-module='product'></div>
<div class="table-empty-tip">
<p><span class="text-muted"><?php echo $lang->product->noProduct;?></span></p>
</div>
<?php else:?>
<div class="main-col">
<div class="cell<?php if($browseType == 'bySearch') echo ' show';?>" id="queryBox" data-module='product'></div>
<form class="main-table table-product" data-ride="table" data-nested='true' id="productListForm" method="post" action='<?php echo inLink('batchEdit', '');?>' data-preserve-nested='false' data-expand-nest-child='true'>
<?php $canBatchEdit = common::hasPriv('product', 'batchEdit'); ?>
<table id="productList" class="table has-sort-head table-nested table-fixed">
@@ -212,7 +215,7 @@
<td><?php echo $product->plans;?></td>
<td><?php echo $product->releases;?></td>
<?php foreach($extendFields as $extendField) echo "<td>" . $this->loadModel('flow')->getFieldValue($extendField, $product) . "</td>";?>
<td class='c-actions sort-handler'><?php echo $this->buildOperateMenu($product, 'browse');?></td>
<td class='c-actions sort-handler'><?php echo $this->product->buildOperateMenu($product, 'browse');?></td>
</tr>
<?php endforeach;?>
<?php endif;?>
@@ -220,17 +223,18 @@
<?php endforeach;?>
</tbody>
</table>
<?php if(!empty($product) and $canBatchEdit):?>
<div class='table-footer'>
<?php echo $pager->show('left', 'pagerjs');?>
<?php if(!empty($product) and $canBatchEdit):?>
<div class="checkbox-primary check-all"><label><?php echo $lang->selectAll?></label></div>
<div class="table-actions btn-toolbar">
<?php
$actionLink = $this->createLink('product', 'batchEdit');
echo html::commonButton($lang->edit, "data-form-action='$actionLink'");
?>
<?php endif;?>
</div>
</div>
<?php endif;?>
</form>
</div>
<?php endif;?>
+1 -1
View File
@@ -161,7 +161,7 @@
$browseLink = $this->session->productList ? $this->session->productList : inlink('browse', "productID=$product->id");
common::printBack($browseLink);
if(!$product->deleted) echo $this->buildOperateMenu($product, 'view');
if(!$product->deleted) echo $this->product->buildOperateMenu($product, 'view');
?>
</div>
</div>
@@ -144,7 +144,7 @@
<div title='<?php echo $desc;?>'><?php echo nl2br($desc);?></div>
</td>
<?php foreach($extendFields as $extendField) echo "<td>" . $this->loadModel('flow')->getFieldValue($extendField, $plan) . "</td>";?>
<td class='c-actions'><?php echo $this->buildOperateMenu($plan, 'browse'); ?></td>
<td class='c-actions'><?php echo $this->productplan->buildOperateMenu($plan, 'browse'); ?></td>
</tr>
<?php endforeach;?>
</tbody>
+1 -1
View File
@@ -38,7 +38,7 @@
</div>
</div>
<div class='btn-toolbar pull-right' id='actionsBox'>
<?php if(!$plan->deleted && !isonlybody()) echo $this->buildOperateMenu($plan, 'view'); ?>
<?php if(!$plan->deleted && !isonlybody()) echo $this->productplan->buildOperateMenu($plan, 'view'); ?>
</div>
</div>
<div id='mainContent' class='main-content'>
+28
View File
@@ -22,3 +22,31 @@ $config->program->sortFields = new stdclass();
$config->program->sortFields->id = 'id';
$config->program->sortFields->begin = 'begin';
$config->program->sortFields->end = 'end';
global $lang;
$config->program->search['module'] = 'program';
$config->program->search['fields']['name'] = $lang->program->name;
$config->program->search['fields']['status'] = $lang->program->status;
$config->program->search['fields']['desc'] = $lang->program->desc;
$config->program->search['fields']['PM'] = $lang->program->PM;
$config->program->search['fields']['openedDate'] = $lang->program->openedDate;
$config->program->search['fields']['begin'] = $lang->program->begin;
$config->program->search['fields']['end'] = $lang->program->end;
$config->program->search['fields']['openedBy'] = $lang->program->openedBy;
$config->program->search['fields']['lastEditedDate'] = $lang->program->lastEditedDate;
$config->program->search['fields']['realBegan'] = $lang->program->realBegin;
$config->program->search['fields']['realEnd'] = $lang->program->realEnd;
$config->program->search['fields']['closedDate'] = $lang->program->closedDate;
$config->program->search['params']['name'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
$config->program->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => array('' => '') + $lang->program->statusList);
$config->program->search['params']['desc'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
$config->program->search['params']['PM'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->program->search['params']['openedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->program->search['params']['begin'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->program->search['params']['end'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->program->search['params']['openedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->program->search['params']['lastEditedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->program->search['params']['realBegan'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->program->search['params']['realEnd'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->program->search['params']['closedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+23 -2
View File
@@ -26,13 +26,16 @@ class program extends control
* @access public
* @return void
*/
public function browse($status = 'all', $orderBy = 'order_asc')
public function browse($status = 'all', $orderBy = 'order_asc', $recTotal = 0, $recPerPage = 10, $pageID = 1, $param = 0)
{
if(common::hasPriv('program', 'create')) $this->lang->pageActions = html::a($this->createLink('program', 'create'), "<i class='icon icon-plus'></i> " . $this->lang->program->create, '', "class='btn btn-primary create-program-btn'");
$this->session->set('programList', $this->app->getURI(true), 'program');
$this->session->set('projectList', $this->app->getURI(true), 'program');
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$programType = $this->cookie->programType ? $this->cookie->programType : 'bylist';
if($programType === 'bygrid')
@@ -41,7 +44,18 @@ class program extends control
}
else
{
$programs = $this->program->getList($status, $orderBy, null, true);
if(strtolower($status) == 'bysearch')
{
$queryID = (int)$param;
$programs = $this->program->getListBySearch($orderBy, $pager, $queryID);
}
else
{
$topPrograms = $this->program->getList($status, $orderBy, $pager, 'top');
$programIds = array();
foreach($topPrograms as $programID => $program) $programIds[] = $programID;
$programs = $this->program->getList($status, $orderBy, null, 'child', $programIds);
}
}
/* Get PM id list. */
@@ -52,12 +66,19 @@ class program extends control
}
$PMList = $this->loadModel('user')->getListByAccounts($accounts, 'account');
/* Build the search form. */
$actionURL = $this->createLink('program', 'browse', "status=bySearch&orderBy={$orderBy}&recTotal={$recTotal}&recPerPage={$recPerPage}&pageID={$pageID}&param=myQueryID");
$this->config->program->search['onMenuBar'] = 'yes';
$this->config->program->search['actionURL'] = $actionURL;
$this->loadModel('search')->setSearchParams($this->config->program->search);
$this->view->title = $this->lang->program->browse;
$this->view->position[] = $this->lang->program->browse;
$this->view->programs = $programs;
$this->view->status = $status;
$this->view->orderBy = $orderBy;
$this->view->pager = $pager;
$this->view->users = $this->user->getPairs('noletter');
$this->view->userIdPairs = $this->user->getPairs('noletter|showid');
$this->view->usersAvatar = $this->user->getAvatarPairs('');
+7
View File
@@ -43,6 +43,13 @@ $(function()
$('#programForm').removeClass('has-row-checked');
}
});
var myPager = $('.pager').data('zui.pager');
if(status != 'bySearch' && myPager)
{
myPager.lang.pageSize = pageSize;
myPager.set();
}
});
function showEditCheckbox(show)
+32 -28
View File
@@ -1,33 +1,36 @@
<?php
/* Fields. */
$lang->program->id = 'ID';
$lang->program->name = 'Name';
$lang->program->template = 'Template';
$lang->program->category = 'Type';
$lang->program->desc = 'Description';
$lang->program->status = 'Status';
$lang->program->PM = 'Manager';
$lang->program->budget = 'Budget';
$lang->program->budgetUnit = 'Budget Unit';
$lang->program->begin = 'Begin';
$lang->program->end = 'End';
$lang->program->stage = 'Stage';
$lang->program->type = 'Type';
$lang->program->pri = 'Priority';
$lang->program->parent = 'Parent';
$lang->program->exchangeRate = 'Exchange Rate';
$lang->program->openedBy = 'OpenedBy';
$lang->program->openedDate = 'OpenedDate';
$lang->program->closedBy = 'ClosedBy';
$lang->program->closedDate = 'ClosedDate';
$lang->program->canceledBy = 'CanceledBy';
$lang->program->canceledDate = 'CanceledDate';
$lang->program->team = 'Team';
$lang->program->order = 'Rank';
$lang->program->days = 'Days';
$lang->program->acl = 'Access Control';
$lang->program->whitelist = 'WhiteList';
$lang->program->deleted = 'Deleted';
$lang->program->id = 'ID';
$lang->program->name = 'Name';
$lang->program->template = 'Template';
$lang->program->category = 'Type';
$lang->program->desc = 'Description';
$lang->program->status = 'Status';
$lang->program->PM = 'Manager';
$lang->program->budget = 'Budget';
$lang->program->budgetUnit = 'Budget Unit';
$lang->program->begin = 'Begin';
$lang->program->end = 'End';
$lang->program->realBegin = 'Actual Begin';
$lang->program->realEnd = 'Actual End';
$lang->program->stage = 'Stage';
$lang->program->type = 'Type';
$lang->program->pri = 'Priority';
$lang->program->parent = 'Parent';
$lang->program->exchangeRate = 'Exchange Rate';
$lang->program->openedBy = 'OpenedBy';
$lang->program->openedDate = 'OpenedDate';
$lang->program->closedBy = 'ClosedBy';
$lang->program->closedDate = 'ClosedDate';
$lang->program->canceledBy = 'CanceledBy';
$lang->program->canceledDate = 'CanceledDate';
$lang->program->lastEditedDate = 'LastEditedDate';
$lang->program->team = 'Team';
$lang->program->order = 'Rank';
$lang->program->days = 'Days';
$lang->program->acl = 'Access Control';
$lang->program->whitelist = 'WhiteList';
$lang->program->deleted = 'Deleted';
/* Actions. */
$lang->program->common = 'Program';
@@ -71,6 +74,7 @@ $lang->program->moreProgram = 'More program';
$lang->program->stakeholderType = 'Stakeholder type';
$lang->program->parentBudget = 'Parent program surplus budget';
$lang->program->isStakeholderKey = 'Key stakeholder';
$lang->program->pageSize = '<strong>{recPerPage}</strong> Top Programs per page';
$lang->program->stakeholderTypeList['inside'] = 'Inside';
$lang->program->stakeholderTypeList['outside'] = 'Outside';
+32 -28
View File
@@ -1,33 +1,36 @@
<?php
/* Fields. */
$lang->program->id = '编号';
$lang->program->name = '项目集名称';
$lang->program->template = '项目集模板';
$lang->program->category = '项目集类型';
$lang->program->desc = '项目集描述';
$lang->program->status = '状态';
$lang->program->PM = '负责人';
$lang->program->budget = '预算';
$lang->program->budgetUnit = '预算单位';
$lang->program->begin = '计划开始';
$lang->program->end = '计划完成';
$lang->program->stage = '阶段';
$lang->program->type = '类型';
$lang->program->pri = '优先级';
$lang->program->parent = '父项目集';
$lang->program->exchangeRate = '汇率';
$lang->program->openedBy = '由谁创建';
$lang->program->openedDate = '创建日期';
$lang->program->closedBy = '由谁关闭';
$lang->program->closedDate = '关闭日期';
$lang->program->canceledBy = '由谁取消';
$lang->program->canceledDate = '取消日期';
$lang->program->team = '团队';
$lang->program->order = '排序';
$lang->program->days = '可用工作日';
$lang->program->acl = '访问控制';
$lang->program->whitelist = '白名单';
$lang->program->deleted = '已删除';
$lang->program->id = '编号';
$lang->program->name = '项目集名称';
$lang->program->template = '项目集模板';
$lang->program->category = '项目集类型';
$lang->program->desc = '项目集描述';
$lang->program->status = '状态';
$lang->program->PM = '负责人';
$lang->program->budget = '预算';
$lang->program->budgetUnit = '预算单位';
$lang->program->begin = '计划开始';
$lang->program->end = '计划完成';
$lang->program->realBegin = '实际开始';
$lang->program->realEnd = '实际完成';
$lang->program->stage = '阶段';
$lang->program->type = '类型';
$lang->program->pri = '优先级';
$lang->program->parent = '父项目集';
$lang->program->exchangeRate = '汇率';
$lang->program->openedBy = '由谁创建';
$lang->program->openedDate = '创建日期';
$lang->program->closedBy = '由谁关闭';
$lang->program->closedDate = '关闭日期';
$lang->program->canceledBy = '由谁取消';
$lang->program->canceledDate = '取消日期';
$lang->program->lastEditedDate = '最后编辑';
$lang->program->team = '团队';
$lang->program->order = '排序';
$lang->program->days = '可用工作日';
$lang->program->acl = '访问控制';
$lang->program->whitelist = '白名单';
$lang->program->deleted = '已删除';
/* Actions. */
$lang->program->common = '项目集';
@@ -71,6 +74,7 @@ $lang->program->moreProgram = '更多项目集';
$lang->program->stakeholderType = '干系人类型';
$lang->program->parentBudget = '所属项目集剩余预算:';
$lang->program->isStakeholderKey = '关键干系人';
$lang->program->pageSize = '每页 <strong>{recPerPage}</strong> 项顶级项目集';
$lang->program->stakeholderTypeList['inside'] = '内部';
$lang->program->stakeholderTypeList['outside'] = '外部';
+63 -4
View File
@@ -130,11 +130,22 @@ class programModel extends model
* @param string $status
* @param string $orderBy
* @param object $pager
* @param string $type top|child
* @param mixed $idList
* @access public
* @return array
*/
public function getList($status = 'all', $orderBy = 'id_asc', $pager = NULL)
public function getList($status = 'all', $orderBy = 'id_asc', $pager = NULL, $type = '', $idList = '')
{
$projectIdList = array();
if($type === 'child')
{
foreach($idList as $topID)
{
$projectIdList += $this->dao->select('id')->from(TABLE_PROGRAM)->Where('path')->like(",$topID,%")->fetchPairs('id');
}
}
return $this->dao->select('*')->from(TABLE_PROGRAM)
->where('deleted')->eq(0)
->andWhere('vision')->eq($this->config->vision)
@@ -146,6 +157,54 @@ class programModel extends model
->markRight(2)
->beginIF($status != 'all')->andWhere('status')->eq($status)->fi()
->beginIF(!$this->cookie->showClosed)->andWhere('status')->ne('closed')->fi()
->beginIF($type === 'top')->andWhere('parent')->eq(0)->fi()
->beginIF(!empty($projectIdList))->andWhere('id')->in($projectIdList)->fi()
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
}
/**
* Get program list by search.
*
* @param string $orderBy
* @param object $pager
* @param int $queryID
* @access public
* @return void
*/
public function getListBySearch($orderBy = 'id_asc', $pager = NULL, $queryID = 0)
{
if($queryID)
{
$query = $this->loadModel('search')->getQuery($queryID);
if($query)
{
$this->session->set('programQuery', $query->sql);
$this->session->set('programForm', $query->form);
}
else
{
$this->session->set('programQuery', ' 1 = 1');
}
}
else
{
if($this->session->programQuery == false) $this->session->set('programQuery', ' 1 = 1');
}
$query = $this->session->programQuery;
return $this->dao->select('*')->from(TABLE_PROGRAM)
->where('deleted')->eq(0)
->andWhere('vision')->eq($this->config->vision)
->andWhere('((type')->eq('program')
->beginIF(!$this->app->user->admin and $this->app->rawMethod != 'browse')->andWhere('id')->in($this->app->user->view->programs)->fi()
->markRight(1)
->orWhere('(type')->eq('project')
->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->projects)->fi()
->markRight(2)
->beginIF(!$this->cookie->showClosed)->andWhere('status')->ne('closed')->fi()
->beginIF($query)->andWhere($query)->fi()
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
@@ -240,15 +299,15 @@ class programModel extends model
foreach($products as $product)
{
$product->plans = zget($plans, $product->id, array());
/* Convert predefined HTML entities to characters. */
!empty($product->plans) && array_map(function($planVal)
{
return $planVal->title = htmlspecialchars_decode($planVal->title, ENT_QUOTES);
},
},
$product->plans);
$product->name = htmlspecialchars_decode($product->name, ENT_QUOTES);
$product->releases = zget($releases, $product->id, array());
$projects = zget($projectGroup, $product->id, array());
foreach($projects as $project)
+4
View File
@@ -15,6 +15,7 @@
<?php js::set('orderBy', $orderBy);?>
<?php js::set('edit', $lang->edit);?>
<?php js::set('selectAll', $lang->selectAll);?>
<?php js::set('pageSize', $lang->program->pageSize);?>
<?php if($programType == 'bygrid'):?>
<style> #mainMenu{padding-left: 10px; padding-right: 10px;} </style>
<?php endif;?>
@@ -27,6 +28,7 @@
<?php endforeach;?>
<?php echo html::checkbox('showClosed', array('1' => $lang->program->showClosed), '', $this->cookie->showClosed ? 'checked=checked' : '');?>
<?php if(common::hasPriv('project', 'batchEdit') and $programType != 'bygrid') echo html::checkbox('editProject', array('1' => $lang->project->edit), '', $this->cookie->editProject ? 'checked=checked' : '');?>
<a class="btn btn-link querybox-toggle" id='bysearchTab'><i class="icon icon-search muted"></i> <?php echo $lang->user->search;?></a>
</div>
<div class='pull-right'>
<?php if(common::hasPriv('project', 'create')) common::printLink('project', 'createGuide', "programID=0&from=PGM", '<i class="icon icon-plus"></i> ' . $lang->project->create, '', 'class="btn btn-secondary" data-toggle="modal" data-target="#guideDialog"');?>
@@ -35,6 +37,7 @@
</div>
<div id='mainContent' class='main-row'>
<?php if(empty($programs)):?>
<div class="cell<?php if($status == 'bySearch') echo ' show';?>" id="queryBox" data-module='program'></div>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->program->noProgram;?></span>
@@ -43,6 +46,7 @@
</div>
<?php else:?>
<div class='main-col'>
<div class="cell<?php if($status == 'bySearch') echo ' show';?>" id="queryBox" data-module='program'></div>
<?php
if($programType == 'bygrid')
{
+4 -3
View File
@@ -119,9 +119,9 @@
</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 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>
@@ -138,6 +138,7 @@
<?php endforeach;?>
</tbody>
</table>
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
</form>
<style>
#programTableList.sortable-sorting > tr {opacity: 0.7}
+37
View File
@@ -132,6 +132,43 @@ $config->project->maxCheckList = new stdclass();
$config->project->maxCheckList->scrum = array('bug', 'execution', 'build', 'doc', 'release', 'testtask', 'case', 'issue', 'risk', 'meeting');
$config->project->maxCheckList->waterfall = array('execution', 'design', 'doc', 'bug', 'case', 'build', 'release', 'testtask', 'review', 'build', 'researchplan', 'issue', 'risk', 'opportunity', 'auditplan', 'gapanalysis', 'meeting');
$config->project->search['module'] = 'project';
$config->project->search['fields']['name'] = $lang->project->name;
$config->project->search['fields']['code'] = $lang->project->code;
$config->project->search['fields']['id'] = $lang->project->id;
$config->project->search['fields']['model'] = $lang->project->model;
$config->project->search['fields']['parent'] = $lang->project->parent;
$config->project->search['fields']['status'] = $lang->project->status;
$config->project->search['fields']['desc'] = $lang->project->desc;
$config->project->search['fields']['PM'] = $lang->project->PM;
$config->project->search['fields']['openedDate'] = $lang->project->openedDate;
$config->project->search['fields']['begin'] = $lang->project->begin;
$config->project->search['fields']['end'] = $lang->project->end;
$config->project->search['fields']['realBegan'] = $lang->project->realBeganAB;
$config->project->search['fields']['realEnd'] = $lang->project->realEndAB;
$config->project->search['fields']['openedBy'] = $lang->project->openedBy;
$config->project->search['fields']['closedBy'] = $lang->project->closedBy;
$config->project->search['fields']['lastEditedDate'] = $lang->project->lastEditedDate;
$config->project->search['fields']['closedDate'] = $lang->project->closedDate;
$config->project->search['params']['name'] = array('operator' => 'include', 'control' => 'input' , 'values' => '');
$config->project->search['params']['code'] = array('operator' => '=' , 'control' => 'input' , 'values' => '');
$config->project->search['params']['id'] = array('operator' => '=' , 'control' => 'input' , 'values' => '');
$config->project->search['params']['model'] = array('operator' => '=' , 'control' => 'select', 'values' => $lang->project->modelList);
$config->project->search['params']['parent'] = array('operator' => '=' , 'control' => 'select', 'values' => '');
$config->project->search['params']['status'] = array('operator' => '=' , 'control' => 'select', 'values' => $lang->project->statusList);
$config->project->search['params']['desc'] = array('operator' => 'include', 'control' => 'input' , 'values' => '');
$config->project->search['params']['PM'] = array('operator' => '=' , 'control' => 'select', 'values' => 'users');
$config->project->search['params']['openedDate'] = array('operator' => '=' , 'control' => 'input' , 'values' => '', 'class' => 'date');
$config->project->search['params']['begin'] = array('operator' => '=' , 'control' => 'input' , 'values' => '', 'class' => 'date');
$config->project->search['params']['end'] = array('operator' => '=' , 'control' => 'input' , 'values' => '', 'class' => 'date');
$config->project->search['params']['realBegan'] = array('operator' => '=' , 'control' => 'input' , 'values' => '', 'class' => 'date');
$config->project->search['params']['realEnd'] = array('operator' => '=' , 'control' => 'input' , 'values' => '', 'class' => 'date');
$config->project->search['params']['openedBy'] = array('operator' => '=' , 'control' => 'select', 'values' => 'users');
$config->project->search['params']['closedBy'] = array('operator' => '=' , 'control' => 'select', 'values' => 'users');
$config->project->search['params']['lastEditedDate'] = array('operator' => '=' , 'control' => 'input' , 'values' => '', 'class' => 'date');
$config->project->search['params']['closedDate'] = array('operator' => '=' , 'control' => 'input' , 'values' => '', 'class' => 'date');
$config->project->includedPriv['project'] = array('edit', 'group', 'createGroup', 'managePriv', 'manageMembers', 'manageGroupMember', 'copyGroup', 'editGroup', 'start', 'suspend', 'close', 'activate', 'delete', 'view', 'whitelist', 'addWhitelist', 'unbindWhitelist', 'manageProducts', 'dynamic', 'build', 'bug', 'testcase', 'testtask', 'testreport', 'execution', 'team', 'unlinkMember');
$config->project->includedPriv['execution'] = array('create', 'start', 'delete', 'calendar', 'effortCalendar', 'effort', 'taskEffort', 'computeTaskEffort', 'deleterelation', 'maintainrelation', 'relation', 'gantt');
$config->project->includedPriv['task'] = array('create');
+5
View File
@@ -308,6 +308,11 @@ class project extends control
$programTitle = $this->loadModel('setting')->getItem('owner=' . $this->app->user->account . '&module=project&key=programTitle');
$projectStats = $this->loadModel('program')->getProjectStats($programID, $browseType, $queryID, $orderBy, $pager, $programTitle);
$actionURL = $this->createLink('project', 'browse', "&programID=$programID&browseType=bySearch&queryID=myQueryID");
$this->project->buildSearchFrom($queryID, $actionURL);
$projectQuery = $this->session->projectQuery;
if($browseType == 'bySearch') $projectStats = $this->project->getBySearch($projectQuery);
$this->view->title = $this->lang->project->browse;
$this->view->position[] = $this->lang->project->browse;
+2
View File
@@ -227,6 +227,7 @@ $lang->project->currencySymbol['NZD'] = 'NZ$';
$lang->project->currencySymbol['THB'] = '฿';
$lang->project->currencySymbol['SGD'] = 'S$';
$lang->project->modelList[''] = '';
$lang->project->modelList['scrum'] = "Scrum";
$lang->project->modelList['waterfall'] = "CMMI";
$lang->project->modelList['kanban'] = "Kanban";
@@ -257,6 +258,7 @@ $lang->project->kanbanSubAclList['program'] = 'Open in the program (all upper-le
$lang->project->authList['extend'] = 'Inherit (system privilege and project privilege)';
$lang->project->authList['reset'] = 'Reset (project privilege only)';
$lang->project->statusList[''] = '';
$lang->project->statusList['wait'] = 'Waiting';
$lang->project->statusList['doing'] = 'Doing';
$lang->project->statusList['suspended'] = 'Suspended';
+2
View File
@@ -227,6 +227,7 @@ $lang->project->currencySymbol['NZD'] = 'NZ$';
$lang->project->currencySymbol['THB'] = '฿';
$lang->project->currencySymbol['SGD'] = 'S$';
$lang->project->modelList[''] = "";
$lang->project->modelList['scrum'] = "Scrum";
$lang->project->modelList['waterfall'] = "瀑布";
$lang->project->modelList['kanban'] = "看板";
@@ -257,6 +258,7 @@ $lang->project->kanbanSubAclList['program'] = '项目集内公开(所有上级
$lang->project->authList['extend'] = '继承 (取系统权限与项目权限的合集)';
$lang->project->authList['reset'] = '重新定义 (只取项目权限)';
$lang->project->statusList[''] = '';
$lang->project->statusList['wait'] = '未开始';
$lang->project->statusList['doing'] = '进行中';
$lang->project->statusList['suspended'] = '已挂起';
+146 -48
View File
@@ -825,6 +825,39 @@ class projectModel extends model
->fetchGroup('productID', 'branchID');
}
/*
* Get projects by search conditions.
*
* @param string $projectQuery
* @return array
* */
public function getBySearch($projectQuery)
{
return $this->dao->select('*')->from(TABLE_PROJECT)
->where($projectQuery)
->andWhere('type')->eq('project')
->fetchAll();
}
/*
* Build search form
*
* @param int $queryID
* @param string $actionURL
*
* @return 0
* */
public function buildSearchFrom($queryID, $actionURL)
{
$this->config->project->search['queryID'] = $queryID;
$this->config->project->search['actionURL'] = $actionURL;
$programPairs = array(0 => '');
$programPairs += $this->loadModel('program')->getPairs();
$this->config->project->search['params']['parent']['values'] = $programPairs;
$this->loadModel('search')->setSearchParams($this->config->project->search);
}
/**
* Build the query.
*
@@ -1959,54 +1992,8 @@ class projectModel extends model
echo html::ring($project->hours->progress);
break;
case 'actions':
$moduleName = $this->config->systemMode == 'classic' ? "execution" : "project";
if($project->status == 'wait' or $project->status == 'suspended') common::printIcon($moduleName, 'start', "projectID=$project->id", $project, 'list', 'play', '', 'iframe', true);
if($project->status == 'doing') common::printIcon($moduleName, 'close', "projectID=$project->id", $project, 'list', 'off', '', 'iframe', true);
if($project->status == 'closed') common::printIcon($moduleName, 'activate', "projectID=$project->id", $project, 'list', 'magic', '', 'iframe', true);
if(common::hasPriv($moduleName, 'suspend') or (common::hasPriv($moduleName, 'close') and $project->status != 'doing') or (common::hasPriv($moduleName, 'activate') && $project->status != 'closed'))
{
echo "<div class='btn-group'>";
echo "<button type='button' class='btn icon-caret-down dropdown-toggle' data-toggle='context-dropdown' title='{$this->lang->more}' style='width: 16px; padding-left: 0px; border-radius: 4px;'></button>";
echo "<ul class='dropdown-menu pull-right text-center' role='menu' style='position: unset; min-width: auto; padding: 5px 6px;'>";
common::printIcon($moduleName, 'suspend', "projectID=$project->id", $project, 'list', 'pause', '', 'iframe btn-action', true);
if($project->status != 'doing') common::printIcon($moduleName, 'close', "projectID=$project->id", $project, 'list', 'off', '', 'iframe btn-action', true);
if($project->status != 'closed') common::printIcon($moduleName, 'activate', "projectID=$project->id", $project, 'list', 'magic', '', 'iframe btn-action', true);
echo "</ul>";
echo "</div>";
}
$from = $project->from == 'project' ? 'project' : 'pgmproject';
$iframe = ($this->app->tab == 'program' or $project->model == 'kanban') ? 'iframe' : '';
$onlyBody = ($this->app->tab == 'program' or $project->model == 'kanban') ? true : '';
$dataApp = $this->config->systemMode == 'classic' ? "data-app=execution" : "data-app=project";
$attr = $project->model == 'kanban' ? " disabled='disabled'" : '';
common::printIcon($moduleName, 'edit', "projectID=$project->id", $project, 'list', 'edit', '', $iframe, $onlyBody, $dataApp);
if($this->config->vision != 'lite')
{
common::printIcon($moduleName, 'team', "projectID=$project->id", $project, 'list', 'group', '', '', '', $dataApp . $attr, $this->lang->execution->team);
if($this->config->systemMode == 'new') common::printIcon('project', 'group', "projectID=$project->id&programID=$programID", $project, 'list', 'lock', '', '', '', $dataApp . $attr);
if(common::hasPriv($moduleName, 'manageProducts') or common::hasPriv($moduleName, 'whitelist') or common::hasPriv($moduleName, 'delete'))
{
echo "<div class='btn-group'>";
echo "<button type='button' class='btn dropdown-toggle' data-toggle='context-dropdown' title='{$this->lang->more}'><i class='icon-more-alt'></i></button>";
echo "<ul class='dropdown-menu pull-right text-center' role='menu'>";
common::printIcon($moduleName, 'manageProducts', "projectID=$project->id", $project, 'list', 'link', '', 'btn-action', '', $attr, $this->lang->project->manageProducts);
if($this->config->systemMode == 'new') common::printIcon('project', 'whitelist', "projectID=$project->id&module=project&from=$from", $project, 'list', 'shield-check', '', 'btn-action', '', $dataApp . $attr);
if(common::hasPriv($moduleName, 'delete')) echo html::a(helper::createLink($moduleName, "delete", "projectID=$project->id"), "<i class='icon-trash'></i>", 'hiddenwin', "class='btn btn-action' title='{$this->lang->project->delete}'");
echo "</ul>";
echo "</div>";
}
}
else
{
common::printIcon($moduleName, 'team', "projectID=$project->id", $project, 'list', 'group', '', '', '', $dataApp, $this->lang->execution->team);
if($this->config->systemMode == 'new') common::printIcon('project', 'whitelist', "projectID=$project->id&module=project&from=$from", $project, 'list', 'shield-check', '', 'btn-action', '', $dataApp);
if(common::hasPriv($moduleName, 'delete')) echo html::a(helper::createLink($moduleName, "delete", "projectID=$project->id"), "<i class='icon-trash'></i>", 'hiddenwin', "class='btn btn-action' title='{$this->lang->project->delete}'");
}
$project->programID = $programID;
echo $this->buildOperateMenu($project, 'browse');
break;
}
echo '</td>';
@@ -2553,4 +2540,115 @@ class projectModel extends model
->fetch();
return $result;
}
/**
* Build project action menu.
*
* @param object $project
* @param string $type
* @access public
* @return string
*/
public function buildOperateMenu($project, $type = 'view')
{
$function = 'buildOperate' . ucfirst($type) . 'Menu';
return $this->$function($project);
}
/**
* Build project view action menu.
*
* @param object $project
* @access public
* @return string
*/
public function buildOperateViewMenu($project)
{
if($project->deleted) return '';
$menu = '';
$params = "projectID=$project->id";
$menu .= "<div class='divider'></div>";
$menu .= $this->buildMenu('project', 'start', $params, $project, 'view', 'play', '', 'iframe', true, '', $this->lang->project->start);
$menu .= $this->buildMenu('project', 'activate', $params, $project, 'view', 'magic', '', 'iframe', true, '', $this->lang->project->activate);
$menu .= $this->buildMenu('project', 'suspend', $params, $project, 'view', 'pause', '', 'iframe', true, '', $this->lang->project->suspend);
$menu .= $this->buildMenu('project', 'close', $params, $project, 'view', 'off', '', 'iframe', true, '', $this->lang->close);
$menu .= "<div class='divider'></div>";
$menu .= $this->buildFlowMenu('project', $project, 'view', 'direct');
$menu .= "<div class='divider'></div>";
$menu .= $this->buildMenu('project', 'edit', "project=$project->id&from=view", $project, 'button', 'edit', '', '', '', '', $this->lang->edit);
$menu .= $this->buildMenu('project', 'delete', "project=$project->id", $project, 'button', 'trash', 'hiddenwin', '', '', '', $this->lang->delete);
return $menu;
}
/**
* Build project browse action menu.
*
* @param object $project
* @access public
* @return string
*/
public function buildOperateBrowseMenu($project)
{
$menu = '';
$params = "projectID=$project->id";
$moduleName = $this->config->systemMode == 'classic' ? "execution" : "project";
if($project->status == 'wait' || $project->status == 'suspended')
{
$menu .= $this->buildMenu($moduleName, 'start', $params, $project, 'browse', 'play', '', 'iframe', true);
}
if($project->status == 'doing') $menu .= $this->buildMenu($moduleName, 'close', $params, $project, 'browse', 'off', '', 'iframe', true);
if($project->status == 'closed') $menu .= $this->buildMenu($moduleName, 'activate', $params, $project, 'browse', 'magic', '', 'iframe', true);
if(common::hasPriv($moduleName, 'suspend') || (common::hasPriv($moduleName, 'close') && $project->status != 'doing') || (common::hasPriv($moduleName, 'activate') && $project->status != 'closed'))
{
$menu .= "<div class='btn-group'>";
$menu .= "<button type='button' class='btn icon-caret-down dropdown-toggle' data-toggle='context-dropdown' title='{$this->lang->more}' style='width: 16px; padding-left: 0px; border-radius: 4px;'></button>";
$menu .= "<ul class='dropdown-menu pull-right text-center' role='menu' style='position: unset; min-width: auto; padding: 5px 6px;'>";
$menu .= $this->buildMenu($moduleName, 'suspend', $params, $project, 'browse', 'pause', '', 'iframe btn-action', true);
if($project->status != 'doing') $menu .= $this->buildMenu($moduleName, 'close', $params, $project, 'browse', 'off', '', 'iframe btn-action', true);
if($project->status != 'closed') $menu .= $this->buildMenu($moduleName, 'activate', $params, $project, 'browse', 'magic', '', 'iframe btn-action', true);
$menu .= "</ul>";
$menu .= "</div>";
}
$from = $project->from == 'project' ? 'project' : 'pgmproject';
$iframe = ($this->app->tab == 'program' || $project->model == 'kanban') ? 'iframe' : '';
$onlyBody = ($this->app->tab == 'program' || $project->model == 'kanban') ? true : '';
$dataApp = $this->config->systemMode == 'classic' ? "data-app=execution" : "data-app=project";
$attr = $project->model == 'kanban' ? " disabled='disabled'" : '';
$menu .= $this->buildMenu($moduleName, 'edit', $params, $project, 'browse', 'edit', '', $iframe, $onlyBody, $dataApp);
if($this->config->vision != 'lite')
{
$menu .= $this->buildMenu($moduleName, 'team', $params, $project, 'browse', 'group', '', '', '', $dataApp . $attr, $this->lang->execution->team);
if($this->config->systemMode == 'new') $menu .= $this->buildMenu('project', 'group', "$params&programID={$project->programID}", $project, 'browse', 'lock', '', '', '', $dataApp . $attr);
if(common::hasPriv($moduleName, 'manageProducts') || common::hasPriv($moduleName, 'whitelist') || common::hasPriv($moduleName, 'delete'))
{
$menu .= "<div class='btn-group'>";
$menu .= "<button type='button' class='btn dropdown-toggle' data-toggle='context-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($moduleName, 'manageProducts', $params, $project, 'browse', 'link', '', 'btn-action', '', $attr, $this->lang->project->manageProducts);
if($this->config->systemMode == 'new') $menu .= $this->buildMenu('project', 'whitelist', "$params&module=project&from=$from", $project, 'browse', 'shield-check', '', 'btn-action', '', $dataApp . $attr);
$menu .= $this->buildMenu($moduleName, "delete", $params, $project, 'browse', 'trash', 'hiddenwin', 'btn-action');
$menu .= "</ul>";
$menu .= "</div>";
}
}
else
{
$menu .= $this->buildMenu($moduleName, 'team', $params, $project, 'browse', 'group', '', '', '', $dataApp, $this->lang->execution->team);
if($this->config->systemMode == 'new') $menu .= $this->buildMenu('project', 'whitelist', "$params&module=project&from=$from", $project, 'browse', 'shield-check', '', 'btn-action', '', $dataApp);
$menu .= $this->buildMenu($moduleName, "delete", $params, $project, 'browse', 'trash', 'hiddenwin', 'btn-action');
}
return $menu;
}
}
@@ -40,6 +40,7 @@
<?php echo html::a(inlink('browse', "programID=$programID&browseType=$key"), $label, '', "class='btn btn-link $active'");?>
<?php endforeach;?>
<?php echo html::checkbox('involved', array('1' => $lang->project->mine), '', $this->cookie->involved ? 'checked=checked' : '');?>
<a class="btn btn-link querybox-toggle" id='bysearchTab'><i class="icon icon-search muted"></i> <?php echo $lang->search->common;?></a>
</div>
<div class="btn-toolbar pull-right">
<div class="btn-group panel-actions">
@@ -67,6 +68,7 @@
</div>
<?php endif;?>
<div class="main-col">
<div class="cell<?php if($browseType == 'bysearch') echo ' show';?>" id="queryBox" data-module='project'></div>
<?php if(empty($projectStats)):?>
<div class="table-empty-tip">
<p>
+3 -19
View File
@@ -96,25 +96,9 @@
</div>
<div class='main-actions'>
<div class="btn-toolbar">
<?php
$params = "project=$project->id";
$browseLink = $this->session->projectList ? $this->session->projectList : inlink('browse');
common::printBack($browseLink);
if(!$project->deleted)
{
echo "<div class='divider'></div>";
common::printIcon('project', 'start', "projectID=$project->id", $project, 'button', 'play', '', 'iframe', true, '', $lang->project->start);
common::printIcon('project', 'activate', "projectID=$project->id", $project, 'button', 'magic', '', 'iframe', true, '', $lang->project->activate);
common::printIcon('project', 'suspend', "projectID=$project->id", $project, 'button', 'pause', '', 'iframe', true, '', $lang->project->suspend);
common::printIcon('project', 'close', "projectID=$project->id", $project, 'button', 'off', '', 'iframe', true, '', $lang->close);
echo $this->buildOperateMenu($project, 'view');
echo "<div class='divider'></div>";
common::printIcon('project', 'edit', $params . '&from=view', $project, 'button', 'edit', '', '', '', '', $lang->edit);
common::printIcon('project', 'delete', $params, $project, 'button', 'trash', 'hiddenwin', '', '', '', $lang->delete);
}
?>
<?php $browseLink = $this->session->projectList ? $this->session->projectList : inlink('browse');?>
<?php common::printBack($browseLink);?>
<?php echo $this->project->buildOperateMenu($project, 'view');?>
</div>
</div>
</div>
+77 -1
View File
@@ -80,7 +80,7 @@ class releaseModel extends model
return $this->dao->select('id, name')->from(TABLE_RELEASE)
->where('product')->eq((int)$productID)
->beginIF($branch)->andWhere('branch')->eq($branch)->fi()
->orderBy('date DESC')
->orderBy('id DESC')
->limit(1)
->fetch();
}
@@ -670,4 +670,80 @@ class releaseModel extends model
$this->loadModel('mail')->send(implode(',', $toList), $subject, $mailContent, '', false, $emails);
}
}
/**
* Build 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 release view action menu.
*
* @param object $release
* @access public
* @return string
*/
public function buildOperateViewMenu($release)
{
$canBeChanged = common::canBeChanged('release', $release);
if($release->deleted || !$canBeChanged || isonlybody()) return '';
$menu = '';
$params = "releaseID=$release->id";
if(common::hasPriv('release', 'changeStatus', $release))
{
$changedStatus = $release->status == 'normal' ? 'terminate' : 'normal';
$menu .= html::a(inlink('changeStatus', "releaseID=$release->id&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>";
$menu .= $this->buildMenu('release', 'edit', $params, $release, 'view');
$menu .= $this->buildMenu('release', 'delete', $params, $release, 'view', 'trash', 'hiddenwin');
return $menu;
}
/**
* Build release browse action menu.
*
* @param object $release
* @access public
* @return string
*/
public function buildOperateBrowseMenu($release)
{
$canBeChanged = common::canBeChanged('release', $release);
if(!$canBeChanged) return '';
$menu = '';
$params = "releaseID=$release->id";
$changedStatus = $release->status == 'normal' ? 'terminate' : 'normal';
if(common::hasPriv('release', '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('release', '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('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);
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}'");
}
return $menu;
}
}
+4 -22
View File
@@ -16,9 +16,9 @@
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
<?php
echo html::a(inlink('browse', "productID={$product->id}&branch=$branch&type=all"), "<span class='text'>{$lang->release->all}</span>" . ($type == 'all' ? ' <span class="label label-light label-badge">' . count($releases) . '</span>' : ''), '', "id='allTab' class='btn btn-link" . ('all' == $type ? ' btn-active-text' : '') . "'");
echo html::a(inlink('browse', "productID={$product->id}&branch=$branch&type=normal"), "<span class='text'>{$lang->release->statusList['normal']}</span>" . ($type == 'normal' ? ' <span class="label label-light label-badge">' . count($releases) . '</span>' : ''), '', "id='normalTab' class='btn btn-link" . ('normal' == $type ? ' btn-active-text' : '') . "'");
echo html::a(inlink('browse', "productID={$product->id}&branch=$branch&type=terminate"), "<span class='text'>{$lang->release->statusList['terminate']}</span>" . ($type == 'terminate' ? ' <span class="label label-light label-badge">' . count($releases) . '</span>' : ''), '', "id='terminateTab' class='btn btn-link" . ('terminate' == $type ? ' btn-active-text' : '') . "'");
echo html::a(inlink('browse', "productID={$product->id}&branch=$branch&type=all"), "<span class='text'>{$lang->release->all}</span>" . ($type == 'all' ? ' <span class="label label-light label-badge">' . $pager->recTotal . '</span>' : ''), '', "id='allTab' class='btn btn-link" . ('all' == $type ? ' btn-active-text' : '') . "'");
echo html::a(inlink('browse', "productID={$product->id}&branch=$branch&type=normal"), "<span class='text'>{$lang->release->statusList['normal']}</span>" . ($type == 'normal' ? ' <span class="label label-light label-badge">' . $pager->recTotal . '</span>' : ''), '', "id='normalTab' class='btn btn-link" . ('normal' == $type ? ' btn-active-text' : '') . "'");
echo html::a(inlink('browse', "productID={$product->id}&branch=$branch&type=terminate"), "<span class='text'>{$lang->release->statusList['terminate']}</span>" . ($type == 'terminate' ? ' <span class="label label-light label-badge">' . $pager->recTotal . '</span>' : ''), '', "id='terminateTab' class='btn btn-link" . ('terminate' == $type ? ' btn-active-text' : '') . "'");
?>
</div>
<div class="btn-toolbar pull-right">
@@ -80,25 +80,7 @@
</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('release', '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('release', '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('release', 'changeStatus', $release))
{
$changedStatus = $release->status == 'normal' ? 'terminate' : 'normal';
echo html::a($this->createLink('release', '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('release', 'edit', "release=$release->id", $release, 'list');
common::printIcon('release', 'notify', "release=$release->id", $release, 'list', 'bullhorn', '', 'iframe', true);
if(common::hasPriv('release', 'delete', $release))
{
$deleteURL = $this->createLink('release', '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}'");
}
}
?>
<?php echo $this->release->buildOperateMenu($release, 'browse');?>
</td>
</tr>
<?php endforeach;?>
+2 -16
View File
@@ -14,6 +14,7 @@
<?php include '../../common/view/tablesorter.html.php';?>
<?php js::set('confirmUnlinkStory', $lang->release->confirmUnlinkStory)?>
<?php js::set('confirmUnlinkBug', $lang->release->confirmUnlinkBug)?>
<?php $canBeChanged = common::canBeChanged('release', $release);?>
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<?php $browseLink = $this->session->releaseList ? $this->session->releaseList : inlink('browse', "productID=$release->product");?>
@@ -30,22 +31,7 @@
</div>
</div>
<div class='btn-toolbar pull-right'>
<?php
$canBeChanged = common::canBeChanged('release', $release);
if(!$release->deleted and $canBeChanged and !isonlybody())
{
echo $this->buildOperateMenu($release, 'view');
if(common::hasPriv('release', '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('release', '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('release', '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'");
}
?>
<?php echo $this->release->buildOperateMenu($release, 'view');?>
</div>
</div>
<div id='mainContent' class='main-content'>
+88 -23
View File
@@ -1987,6 +1987,7 @@ class storyModel extends model
->add('lastEditedBy', $this->app->user->account)
->add('lastEditedDate', $now)
->add('assignedDate', $now)
->remove('comment')
->get();
$this->dao->update(TABLE_STORY)->data($story)->autoCheck()->checkFlow()->where('id')->eq((int)$storyID)->exec();
@@ -3760,6 +3761,92 @@ class storyModel extends model
return true;
}
/**
* Build operate menu.
*
* @param object $story
* @param string $type
* @access public
* @return string
*/
public function buildOperateMenu($story, $type = 'view')
{
$menu = '';
$params = "storyID=$story->id";
if($type == 'browse')
{
if(common::canBeChanged('story', $story))
{
if($story->URChanged) return $this->buildMenu('story', 'processStoryChange', $params, $story, $type, 'search', '', 'iframe', true, '', $this->lang->confirm);
$menu .= $this->buildMenu('story', 'change', $params . "&from=$story->from", $story, $type, 'alter');
$menu .= $this->buildMenu('story', 'review', $params . "&from=$story->from", $story, $type, 'search');
$menu .= $this->buildMenu('story', 'recall', $params, $story, $type, 'undo', 'hiddenwin', '', '', '', $this->lang->story->recall);
$menu .= $this->buildMenu('story', 'close', $params, $story, $type, '', '', 'iframe', true);
$menu .= $this->buildMenu('story', 'edit', $params . "&from=$story->from", $story, $type);
if($story->type != 'requirement' and $this->config->vision != 'lite') $menu .= $this->buildMenu('story', 'createCase', "productID=$story->product&branch=$story->branch&module=0&from=&param=0&$params", $story, $type, 'sitemap', '', '', false, "data-app='qa'");
if($this->app->rawModule != 'projectstory' OR $this->config->vision == 'lite') $menu .= $this->buildMenu('story', 'batchCreate', "productID=$story->product&branch=$story->branch&module=$story->module&$params&executionID={$this->session->project}", $story, $type, 'split', '', '', '', '', $this->lang->story->subdivide);
if($this->app->rawModule == 'projectstory' and $this->config->vision != 'lite') $menu .= $this->buildMenu('projectstory', 'unlinkStory', "projectID={$this->session->project}&$params", $story, $type, 'unlink', 'hiddenwin');
}
else
{
return $this->buildMenu('story', 'close', $params, $story, 'list', '', '', 'iframe', true);
}
}
if($type == 'view')
{
$menu .= $this->buildMenu('story', 'change', $params, $story, $type, 'alter', '', 'showinonlybody');
$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);
$menu .= $this->buildMenu('story', 'assignTo', $params, $story, $type, '', '', 'iframe showinonlybody', true);
$menu .= $this->buildMenu('story', 'close', $params, $story, $type, '', '', 'iframe showinonlybody', true);
$menu .= $this->buildMenu('story', 'activate', $params, $story, $type, '', '', 'iframe showinonlybody', true);
if($this->config->edition == 'max' and $this->app->tab == 'project' and common::hasPriv('story', 'importToLib')) $menu .= html::a('#importToLib', "<i class='icon icon-assets'></i> " . $this->lang->story->importToLib, '', 'class="btn" data-toggle="modal"');
/* Print testcate actions. */
if($story->parent >= 0 and $story->type != 'requirement' and (common::hasPriv('testcase', 'create', $story) or common::hasPriv('testcase', 'batchCreate', $story)))
{
$this->app->loadLang('testcase');
$menu .= "<div class='btn-group dropup'>";
$menu .= "<button type='button' class='btn dropdown-toggle' data-toggle='dropdown'><i class='icon icon-sitemap'></i> " . $this->lang->testcase->common . " <span class='caret'></span></button>";
$menu .= "<ul class='dropdown-menu' id='createCaseActionMenu'>";
$misc = "data-toggle='modal' data-type='iframe' data-width='95%'";
if(isonlybody()) $misc = '';
if(common::hasPriv('testcase', 'create', $story))
{
$link = helper::createLink('testcase', 'create', "productID=$story->product&branch=$story->branch&moduleID=0&from=&param=0&$params", '', true);
$menu .= "<li>" . html::a($link, $this->lang->testcase->create, '', $misc) . "</li>";
}
if(common::hasPriv('testcase', 'batchCreate'))
{
$link = helper::createLink('testcase', 'batchCreate', "productID=$story->product&branch=$story->branch&moduleID=0&$params", '', true);
$menu .= "<li>" . html::a($link, $this->lang->testcase->batchCreate, '', $misc) . "</li>";
}
$menu .= "</ul></div>";
}
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->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);
}
return $menu;
}
/**
* Merge plan title.
*
@@ -4164,29 +4251,7 @@ class storyModel extends model
echo $story->version;
break;
case 'actions':
$vars = "story={$story->id}";
$executionParams = $this->config->vision == 'lite' ? "&executionID={$this->session->project}" : '';
if($canBeChanged)
{
if($story->URChanged)
{
common::printIcon('story', 'processStoryChange', "storyID=$story->id", '', 'list', 'search', '', 'iframe', true, '', $this->lang->confirm);
break;
}
common::printIcon('story', 'change', $vars . "&from=$story->from", $story, 'list', 'alter', '', '', false, "data-group=$story->from");
common::printIcon('story', 'review', $vars . "&from=$story->from", $story, 'list', 'search', '', '', false, "data-group=$story->from");
common::printIcon('story', 'recall', $vars, $story, 'list', 'undo', 'hiddenwin', '', '', '', $this->lang->story->recall);
common::printIcon('story', 'close', $vars, $story, 'list', '', '', 'iframe', true);
common::printIcon('story', 'edit', $vars . "&from=$story->from", $story, 'list', '', '', '', false, "data-group=$story->from");
if($story->type != 'requirement' and $this->config->vision != 'lite') common::printIcon('story', 'createCase', "productID=$story->product&branch=$story->branch&module=0&from=&param=0&$vars", $story, 'list', 'sitemap', '', '', false, "data-app='qa'");
if($this->app->rawModule != 'projectstory' OR $this->config->vision == 'lite') common::printIcon('story', 'batchCreate', "productID=$story->product&branch=$story->branch&module=$story->module&storyID=$story->id" . $executionParams, $story, 'list', 'split', '', '', '', '', $this->lang->story->subdivide);
if($this->app->rawModule == 'projectstory' and $this->config->vision != 'lite') common::printIcon('projectstory', 'unlinkStory', "projectID={$this->session->project}&storyID=$story->id", '', 'list', 'unlink', 'hiddenwin');
}
else
{
common::printIcon('story', 'close', $vars, $story, 'list', '', '', 'iframe', true);
}
echo $this->buildOperateMenu($story, 'browse');
break;
}
echo '</td>';
+1 -47
View File
@@ -200,53 +200,7 @@
<div class="btn-toolbar">
<?php common::printBack($browseLink);?>
<?php if(!isonlybody()) echo "<div class='divider'></div>";?>
<?php if(!$story->deleted):?>
<?php
common::printIcon('story', 'change', "storyID=$story->id", $story, 'button', 'alter', '', 'showinonlybody');
common::printIcon('story', 'recall', "storyID=$story->id", $story, 'button', 'undo', '', 'showinonlybody');
common::printIcon('story', 'review', "storyID=$story->id", $story, 'button', 'search', '', 'showinonlybody');
if($story->status == 'active' and $story->stage == 'wait' and $story->parent <= 0 and !isonlybody())
{
$divideLang = $lang->story->subdivide;
$misc = "class='btn divideStory' data-toggle='modal' data-type='iframe' data-width='95%'";
$link = $this->createLink('story', 'batchCreate', "productID=$story->product&branch=$story->branch&moduleID=$story->module&storyID=$story->id", '', true);
if(common::hasPriv('story', 'batchCreate', $story)) echo html::a($link, "<i class='icon icon-split'></i> " . $divideLang, '', $misc);
}
common::printIcon('story', 'assignTo', "storyID=$story->id", $story, 'button', '', '', 'iframe showinonlybody', true);
common::printIcon('story', 'close', "storyID=$story->id", $story, 'button', '', '', 'iframe showinonlybody', true);
common::printIcon('story', 'activate', "storyID=$story->id", $story, 'button', '', '', 'iframe showinonlybody', true);
if($this->config->edition == 'max' and $this->app->tab == 'project' and common::hasPriv('story', 'importToLib')) echo html::a('#importToLib', "<i class='icon icon-assets'></i> " . $this->lang->story->importToLib, '', 'class="btn" data-toggle="modal"');
if($story->parent >= 0 and $story->type != 'requirement' and (common::hasPriv('testcase', 'create', $story) or common::hasPriv('testcase', 'batchCreate', $story)))
{
$this->app->loadLang('testcase');
echo "<div class='btn-group dropup'>";
echo "<button type='button' class='btn dropdown-toggle' data-toggle='dropdown'><i class='icon icon-sitemap'></i> " . $lang->testcase->common . " <span class='caret'></span></button>";
echo "<ul class='dropdown-menu' id='createCaseActionMenu'>";
$misc = "data-toggle='modal' data-type='iframe' data-width='95%'";
if(isonlybody()) $misc = '';
$link = $this->createLink('testcase', 'create', "productID=$story->product&branch=$story->branch&moduleID=0&from=&param=0&storyID=$story->id", '', true);
if(common::hasPriv('testcase', 'create', $story)) echo "<li>" . html::a($link, $lang->testcase->create, '', $misc) . "</li>";
$link = $this->createLink('testcase', 'batchCreate', "productID=$story->product&branch=$story->branch&moduleID=0&storyID=$story->id", '', true);
if(common::hasPriv('testcase', 'batchCreate')) echo "<li>" . html::a($link, $lang->testcase->batchCreate, '', $misc) . "</li>";
echo "</ul>";
echo "</div>";
}
if($from == 'execution' and strpos('draft,closed', $story->status) === false) common::printIcon('task', 'create', "execution=$param&storyID=$story->id&moduleID=$story->module", $story, 'button', 'plus', '', 'showinonlybody');
echo $this->buildOperateMenu($story, 'view');
echo "<div class='divider'></div>";
common::printIcon('story', 'edit', "storyID=$story->id", $story);
common::printIcon('story', 'create', "productID=$story->product&branch=$story->branch&moduleID=$story->module&storyID=$story->id&executionID=0&bugID=0&planID=0&todoID=0&extra=&type=$story->type", $story, 'button', 'copy', '', '', '', "data-width='1050'");
common::printIcon('story', 'delete', "storyID=$story->id", $story, 'button', 'trash', 'hiddenwin', 'showinonlybody',true);
?>
<?php endif;?>
<?php if(!$story->deleted) echo $this->story->buildOperateMenu($story, 'view');?>
</div>
</div>
</div>
+83 -14
View File
@@ -3399,20 +3399,7 @@ class taskModel extends model
echo helper::isZeroDate($task->activatedDate) ? '' : substr($task->activatedDate, 5, 11);
break;
case 'actions':
if($storyChanged)
{
common::printIcon('task', 'confirmStoryChange', "taskid=$task->id", $task, 'list', '', 'hiddenwin');
break;
}
if($task->status != 'pause') common::printIcon('task', 'start', "taskID=$task->id", $task, 'list', '', '', 'iframe', true);
if($task->status == 'pause') common::printIcon('task', 'restart', "taskID=$task->id", $task, 'list', '', '', 'iframe', true);
common::printIcon('task', 'close', "taskID=$task->id", $task, 'list', '', '', 'iframe', true);
common::printIcon('task', 'finish', "taskID=$task->id", $task, 'list', '', '', 'iframe', true);
common::printIcon('task', 'recordEstimate', "taskID=$task->id", $task, 'list', 'time', '', 'iframe', true);
common::printIcon('task', 'edit', "taskID=$task->id", $task, 'list');
if($this->config->vision == 'rnd') common::printIcon('task', 'batchCreate', "execution=$task->execution&storyID=$task->story&moduleID=$task->module&taskID=$task->id&ifame=0", $task, 'list', 'split', '', '', '', '', $this->lang->task->children);
echo $this->buildOperateMenu($task, 'browse');
break;
}
echo '</td>';
@@ -3535,4 +3522,86 @@ class taskModel extends model
}
return $members;
}
/**
* Build task menu.
*
* @param object $task
* @param string $type
* @access public
* @return string
*/
public function buildOperateMenu($task, $type = 'view')
{
$function = 'buildOperate' . ucfirst($type) . 'Menu';
return $this->$function($task);
}
/**
* Build task view menu.
*
* @param object $task
* @access public
* @return string
*/
public function buildOperateViewMenu($task)
{
if($task->deleted) return '';
$menu = '';
$params = "taskID=$task->id";
if((empty($task->team) || empty($task->children)) && $task->executionList->type != 'kanban')
{
$menu .= $this->buildMenu('task', 'batchCreate', "execution=$task->execution&storyID=$task->story&moduleID=$task->module&taskID=$task->id", $task, 'view', 'split', '', '', '', "title='{$this->lang->task->children}'", $this->lang->task->children);
}
$menu .= $this->buildMenu('task', 'assignTo', "executionID=$task->execution&taskID=$task->id", $task, 'button', '', '', 'iframe', true, '', empty($task->team) ? $this->lang->task->assignTo : $this->lang->task->transfer);
$menu .= $this->buildMenu('task', 'start', $params, $task, 'view', '', '', 'iframe showinonlybody', true);
$menu .= $this->buildMenu('task', 'restart', $params, $task, 'view', '', '', 'iframe showinonlybody', true);
$menu .= $this->buildMenu('task', 'recordEstimate', $params, $task, 'view', '', '', 'iframe showinonlybody', true);
$menu .= $this->buildMenu('task', 'pause', $params, $task, 'view', '', '', 'iframe showinonlybody', true);
$menu .= $this->buildMenu('task', 'finish', $params, $task, 'view', '', '', 'iframe showinonlybody text-success', true);
$menu .= $this->buildMenu('task', 'activate', $params, $task, 'view', '', '', 'iframe showinonlybody text-success', true);
$menu .= $this->buildMenu('task', 'close', $params, $task, 'view', '', '', 'iframe showinonlybody', true);
$menu .= $this->buildMenu('task', 'cancel', $params, $task, 'view', '', '', 'iframe showinonlybody', true);
$menu .= "<div class='divider'></div>";
$menu .= $this->buildFlowMenu('task', $task, 'view', 'direct');
$menu .= "<div class='divider'></div>";
$menu .= $this->buildMenu('task', 'edit', $params, $task, 'view', '', '', 'showinonlybody');
$menu .= $this->buildMenu('task', 'create', "projctID={$task->execution}&storyID=0&moduleID=0&taskID=$task->id", $task, 'view', 'copy');
$menu .= $this->buildMenu('task', 'delete', "executionID=$task->execution&taskID=$task->id", $task, 'view', 'trash', 'hiddenwin', 'showinonlybody', true);
if($task->parent > 0) $menu .= $this->buildMenu('task', 'view', "taskID=$task->parent", $task, 'view', 'chevron-double-up', '', '', '', '', $this->lang->task->parent);
return $menu;
}
/**
* Build task browse action menu.
*
* @param object $task
* @access public
* @return string
*/
public function buildOperateBrowseMenu($task)
{
$menu = '';
$params = "taskID=$task->id";
$storyChanged = !empty($task->storyStatus) && $task->storyStatus == 'active' && $task->latestStoryVersion > $task->storyVersion && !in_array($task->status, array('cancel', 'closed'));
if($storyChanged) return $this->buildMenu('task', 'confirmStoryChange', $params, $task, 'browse', '', 'hiddenwin');
if($task->status != 'pause') $menu .= $this->buildMenu('task', 'start', $params, $task, 'browse', '', '', 'iframe', true);
if($task->status == 'pause') $menu .= $this->buildMenu('task', 'restart', $params, $task, 'browse', '', '', 'iframe', true);
$menu .= $this->buildMenu('task', 'close', $params, $task, 'browse', '', '', 'iframe', true);
$menu .= $this->buildMenu('task', 'finish', $params, $task, 'browse', '', '', 'iframe', true);
$menu .= $this->buildMenu('task', 'recordEstimate', $params, $task, 'browse', 'time', '', 'iframe', true);
$menu .= $this->buildMenu('task', 'edit', $params, $task, 'browse');
if($this->config->vision == 'rnd')
{
$menu .= $this->buildMenu('task', 'batchCreate', "execution=$task->execution&storyID=$task->story&moduleID=$task->module&taskID=$task->id&ifame=0", $task, 'browse', 'split', '', '', '', '', $this->lang->task->children);
}
return $menu;
}
}
+2 -22
View File
@@ -169,28 +169,8 @@
<div class="btn-toolbar">
<?php common::printBack($browseLink);?>
<?php if(!isonlybody()) echo "<div class='divider'></div>";?>
<?php if(!$task->deleted):?>
<?php
if((empty($task->team) or empty($task->children)) and $execution->type != 'kanban') common::printIcon('task', 'batchCreate', "execution=$task->execution&storyID=$task->story&moduleID=$task->module&taskID=$task->id", $task, 'button', 'split', '', '', '', "title='{$lang->task->children}'", $lang->task->children);
common::printIcon('task', 'assignTo', "executionID=$task->execution&taskID=$task->id", $task, 'button', '', '', 'iframe', true, '', empty($task->team) ? $lang->task->assignTo : $lang->task->transfer);
common::printIcon('task', 'start', "taskID=$task->id", $task, 'button', '', '', 'iframe showinonlybody', true);
common::printIcon('task', 'restart', "taskID=$task->id", $task, 'button', '', '', 'iframe showinonlybody', true);
common::printIcon('task', 'recordEstimate', "taskID=$task->id", $task, 'button', '', '', 'iframe showinonlybody', true);
common::printIcon('task', 'pause', "taskID=$task->id", $task, 'button', '', '', 'iframe showinonlybody', true);
common::printIcon('task', 'finish', "taskID=$task->id", $task, 'button', '', '', 'iframe showinonlybody text-success', true);
common::printIcon('task', 'activate', "taskID=$task->id", $task, 'button', '', '', 'iframe showinonlybody text-success', true);
common::printIcon('task', 'close', "taskID=$task->id", $task, 'button', '', '', 'iframe showinonlybody', true);
common::printIcon('task', 'cancel', "taskID=$task->id", $task, 'button', '', '', 'iframe showinonlybody', true);
echo $this->buildOperateMenu($task, 'view');
if(!isonlybody()) echo "<div class='divider'></div>";
common::printIcon('task', 'edit', "taskID=$task->id", $task, 'button', '', '', 'showinonlybody');
common::printIcon('task', 'create', "projctID={$task->execution}&storyID=0&moduleID=0&taskID=$task->id", $task, 'button', 'copy');
common::printIcon('task', 'delete', "executionID=$task->execution&taskID=$task->id", $task, 'button', 'trash', 'hiddenwin', 'showinonlybody', true);
if($task->parent > 0) echo html::a(helper::createLink('task', 'view', "taskID=$task->parent"), "<i class='icon icon-chevron-double-up'></i>", '', "class='btn btn-link' title='{$lang->task->parent}'");
?>
<?php endif;?>
<?php $task->executionList = $execution;?>
<?php echo $this->task->buildOperateMenu($task, 'view');?>
</div>
</div>
</div>
+4 -3
View File
@@ -1169,15 +1169,16 @@ class testcaseModel extends model
*
* @param object $case
* @param string $action
* @param string $module
* @access public
* @return void
*/
public static function isClickable($case, $action)
public static function isClickable($case, $action, $module = 'testcase')
{
$action = strtolower($action);
if($action == 'createbug') return $case->caseFails > 0;
if($action == 'review') return isset($case->caseStatus) ? $case->caseStatus == 'wait' : $case->status == 'wait';
if($module == 'testcase' && $action == 'createbug') return $case->caseFails > 0;
if($module == 'testcase' && $action == 'review') return isset($case->caseStatus) ? $case->caseStatus == 'wait' : $case->status == 'wait';
return true;
}
+1 -1
View File
@@ -116,7 +116,7 @@
<?php $case->isLibCase = $isLibCase;?>
<?php $case->caseFails = $caseFails;?>
<?php $case->runID = $runID;?>
<?php echo $this->buildOperateMenu($case, 'view');?>
<?php echo $this->testcase->buildOperateMenu($case, 'view');?>
</div>
</div>
</div>
+1 -1
View File
@@ -70,7 +70,7 @@
<td><?php echo $suite->addedDate;?></td>
<?php foreach($extendFields as $extendField) echo "<td>" . $this->loadModel('flow')->getFieldValue($extendField, $suite) . "</td>";?>
<td class='c-actions'>
<?php echo $this->buildOperateMenu($suite, 'browse');?>
<?php echo $this->testsuite->buildOperateMenu($suite, 'browse');?>
</td>
</tr>
<?php endforeach;?>
+1 -1
View File
@@ -31,7 +31,7 @@
<?php
if(!$suite->deleted and $canBeChanged)
{
echo $this->buildOperateMenu($suite, 'view');
echo $this->testsuite->buildOperateMenu($suite, 'view');
}
?>
</div>
+1 -1
View File
@@ -102,7 +102,7 @@ $status = $this->session->testTaskVersionStatus;
</td>
<?php foreach($extendFields as $extendField) echo "<td>" . $this->loadModel('flow')->getFieldValue($extendField, $task) . "</td>";?>
<td class='c-actions'>
<?php echo $this->buildOperateMenu($task, 'browse');?>
<?php echo $this->testtask->buildOperateMenu($task, 'browse');?>
</td>
</tr>
<?php endforeach;?>
+1 -1
View File
@@ -51,7 +51,7 @@
<div class="btn-toolbar">
<?php echo html::backButton('<i class="icon icon-back icon-sm"></i> ' . $lang->goback, '', 'btn btn-secondary');?>
<div class='divider'></div>
<?php echo $this->buildOperateMenu($task, 'view');?>
<?php echo $this->testtask->buildOperateMenu($task, 'view');?>
</div>
</div>
</div>
+21
View File
@@ -2024,4 +2024,25 @@ class bugTest
return $array;
}
}
/**
* Test get bug query.
*
* @param string $bugQuery
* @access public
* @return array
*/
public function getBugQueryTest($bugQuery)
{
$array = $this->objectModel->getBugQuery($bugQuery);
if(dao::isError())
{
return dao::getError();
}
else
{
return $array;
}
}
}
+4 -3
View File
@@ -518,20 +518,21 @@ class kanbanTest
*
* @param int $kanbanID
* @param string $fromType
* @param int $archived
* @access public
* @return string
*/
public function getImportedCardsTest($kanbanID, $fromType)
public function getImportedCardsTest($kanbanID, $fromType, $archived = 0)
{
global $tester;
$cards = $tester->dao->select('*')->from(TABLE_KANBANCARD)
->where('deleted')->eq(0)
->andWhere('kanban')->eq($kanbanID)
->andWhere('archived')->eq(0)
->andWhere('archived')->eq($archived)
->andWhere('fromID')->eq(0)
->fetchAll('id');
$objects = $this->objectModel->getImportedCards($kanbanID, $cards, $fromType);
$objects = $this->objectModel->getImportedCards($kanbanID, $cards, $fromType, $archived);
if(dao::isError()) return dao::getError();
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/bug.class.php';
su('admin');
/**
title=bugModel->getBugQuery();
cid=1
pid=1
查询 `product` = 'all' 的bugQuery >> 1 AND `product` IN ('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','65','66','67','68','69','70','71','72','73','74','75','76','77','78','79','80','81','82','83','84','85','86','87','88','89','90','91','92','93','94','95','96','97','98','99','100','101','102','103','104','105','106','107','108','109','110','111','112','113','114','115','116','117','118','119','120','1','2','3','4','5','6','7','8','9','10','21','22','23','24','25','26','27','28','29','30','41','42','43','44','45','46','47','48','49','50','61','62','63','64','65','66','67','68','69','70','81','82','83','84','85','86','87','88','89','90','101','102','103','104','105','106','107','108','109','110
查询 `project` = 'all' 的bugQuery >> 1 AND `project` in (11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750)
查询 `resolvedDate` = '2022-01-01' 的bugQuery >> `resolvedDate` != '0000-00-00 00:00:00' AND `resolvedDate` > '2022-01-01'
查询 `closedDate` = '2022-01-01' 的bugQuery >> `closedDate` != '0000-00-00 00:00:00' AND `closedDate` <= '2022-01-01'
查询 `story` LIKE '%abc%' 的bugQuery >> `story` IN (2,12,20,21,22,23,24,25,26,27,28,29,32,42,52,62,70,71,72,73,74,75,76,77,78,79,82,92,102,112,120,121,122,123,124,125,126,127,128,129,132,142,152,162,172,182,192,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,302,312,320,321,322,323,324,325,326,327,328,329,332,342,352,362,372,382,392,402,412,420,421,422,423,424,425,426,427,428,429,432,442) AND `story` != 0
查询 `story` NOT LIKE '%abc%' 的bugQuery >> `story` NOT IN (2,12,20,21,22,23,24,25,26,27,28,29,32,42,52,62,70,71,72,73,74,75,76,77,78,79,82,92,102,112,120,121,122,123,124,125,126,127,128,129,132,142,152,162,172,182,192,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,302,312,320,321,322,323,324,325,326,327,328,329,332,342,352,362,372,382,392,402,412,420,421,422,423,424,425,426,427,428,429,432,442) AND `story` != 0
查询 `product` = '1' and `project` = '1' and `story` > 'abc' 的bugQuery >> `product` = '1' and `project` = '1' and `story` > 'abc' AND `story` != 0
*/
$bugQuery = array();
$bugQuery[] = "`product` = 'all'";
$bugQuery[] = "`project` = 'all'";
$bugQuery[] = " `resolvedDate` > '2022-01-01'";
$bugQuery[] = " `closedDate` <= '2022-01-01'";
$bugQuery[] = " `story` LIKE '%2%'";
$bugQuery[] = " `story` NOT LIKE '%2%'";
$bugQuery[] = " `product` = '1' and `project` = '1' and `story` > 'abc'";
$bug=new bugTest();
r($bug->getBugQueryTest($bugQuery[0])) && p() && e("1 AND `product` IN ('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','65','66','67','68','69','70','71','72','73','74','75','76','77','78','79','80','81','82','83','84','85','86','87','88','89','90','91','92','93','94','95','96','97','98','99','100','101','102','103','104','105','106','107','108','109','110','111','112','113','114','115','116','117','118','119','120','1','2','3','4','5','6','7','8','9','10','21','22','23','24','25','26','27','28','29','30','41','42','43','44','45','46','47','48','49','50','61','62','63','64','65','66','67','68','69','70','81','82','83','84','85','86','87','88','89','90','101','102','103','104','105','106','107','108','109','110')"); // 查询 `product` = 'all' 的bugQuery
r($bug->getBugQueryTest($bugQuery[1])) && p() && e("1 AND `project` in (11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750)"); // 查询 `project` = 'all' 的bugQuery
r($bug->getBugQueryTest($bugQuery[2])) && p() && e(" `resolvedDate` != '0000-00-00 00:00:00' AND `resolvedDate` > '2022-01-01'"); // 查询 `resolvedDate` = '2022-01-01' 的bugQuery
r($bug->getBugQueryTest($bugQuery[3])) && p() && e(" `closedDate` != '0000-00-00 00:00:00' AND `closedDate` <= '2022-01-01'"); // 查询 `closedDate` = '2022-01-01' 的bugQuery
r($bug->getBugQueryTest($bugQuery[4])) && p() && e(" `story` IN (2,12,20,21,22,23,24,25,26,27,28,29,32,42,52,62,70,71,72,73,74,75,76,77,78,79,82,92,102,112,120,121,122,123,124,125,126,127,128,129,132,142,152,162,172,182,192,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,302,312,320,321,322,323,324,325,326,327,328,329,332,342,352,362,372,382,392,402,412,420,421,422,423,424,425,426,427,428,429,432,442) AND `story` != 0"); // 查询 `story` LIKE '%abc%' 的bugQuery
r($bug->getBugQueryTest($bugQuery[5])) && p() && e(" `story` NOT IN (2,12,20,21,22,23,24,25,26,27,28,29,32,42,52,62,70,71,72,73,74,75,76,77,78,79,82,92,102,112,120,121,122,123,124,125,126,127,128,129,132,142,152,162,172,182,192,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,302,312,320,321,322,323,324,325,326,327,328,329,332,342,352,362,372,382,392,402,412,420,421,422,423,424,425,426,427,428,429,432,442) AND `story` != 0"); // 查询 `story` NOT LIKE '%abc%' 的bugQuery
r($bug->getBugQueryTest($bugQuery[6])) && p() && e("`product` = '1' and `project` = '1' and `story` > 'abc' AND `story` != 0"); // 查询 `product` = '1' and `project` = '1' and `story` > 'abc' 的bugQuery
+7 -1
View File
@@ -26,11 +26,13 @@ pid=1
查看看板23的普通卡片和productplan片 >> ,177,178,179,180,181,182,183,184
查看看板25的普通卡片和build卡片 >> ,193,194,195,196,197,198,199,200,993,994,995,996,997,998,999,1000
查看看板25的普通卡片和productplan片 >> ,193,194,195,196,197,198,199,200
查看看板1已归档的普通卡片和productplan卡片 >> ,6,7,8,801,802,803,804,805,806,807,808
*/
$kanbanIDList = array('1', '2', '9', '10', '11', '12', '23', '25');
$fromType = array('productplan', 'release', 'execution', 'build');
$archived = 1;
$kanban = new kanbanTest();
@@ -49,4 +51,8 @@ r($kanban->getImportedCardstest($kanbanIDList[5], $fromType[3])) && p() && e(',8
r($kanban->getImportedCardstest($kanbanIDList[6], $fromType[3])) && p() && e(',177,178,179,180,181,182,183,184,981,982,983,984'); // 查看看板23的普通卡片和build卡片
r($kanban->getImportedCardstest($kanbanIDList[6], $fromType[0])) && p() && e(',177,178,179,180,181,182,183,184'); // 查看看板23的普通卡片和productplan片
r($kanban->getImportedCardstest($kanbanIDList[7], $fromType[3])) && p() && e(',193,194,195,196,197,198,199,200,993,994,995,996,997,998,999,1000'); // 查看看板25的普通卡片和build卡片
r($kanban->getImportedCardstest($kanbanIDList[7], $fromType[0])) && p() && e(',193,194,195,196,197,198,199,200'); // 查看看板25的普通卡片和productplan片
r($kanban->getImportedCardstest($kanbanIDList[7], $fromType[0])) && p() && e(',193,194,195,196,197,198,199,200'); // 查看看板25的普通卡片和productplan片
global $tester;
$tester->dao->update(TABLE_KANBANCARD)->set('archived')->eq(1)->where('id')->gt('5')->exec();
r($kanban->getImportedCardsTest($kanbanIDList[0], $fromType[0], $archived)) && p() && e(',6,7,8,801,802,803,804,805,806,807,808'); // 查看看板1已归档的普通卡片和productplan卡片
$tester->dao->update(TABLE_KANBANCARD)->set('archived')->eq(0)->where('id')->gt('5')->exec();