Merge branch 'master' of https://gitlab.zcorp.cc/easycorp/zentaopms into sprint/189_tianshujie_task53655
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
sonarqube:
|
||||
variables:
|
||||
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
|
||||
GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task
|
||||
cache:
|
||||
key: "${CI_JOB_NAME}"
|
||||
paths:
|
||||
- .sonar/cache
|
||||
script:
|
||||
- sonar-scanner -Dsonar.inclusions=$(git diff --name-only HEAD~1|tr '\n' ',')
|
||||
allow_failure: true
|
||||
only:
|
||||
- master # or the name of your main branch
|
||||
@@ -89,3 +89,326 @@ REPLACE INTO `zt_zoutput` (`id`, `activity`, `name`, `content`, `optional`, `sta
|
||||
DELETE FROM `zt_config` WHERE `section` = 'customMenu';
|
||||
|
||||
UPDATE `zt_story` SET `plan` = '' WHERE `plan` = 0;
|
||||
|
||||
UPDATE `zt_workflowfield` set `control` = 'datetime' WHERE `module` = 'testcase' and `field` IN ('openedDate','reviewedDate','lastEditedDate','lastRunDate');
|
||||
|
||||
UPDATE `zt_workflowfield` set `control` = 'date' WHERE `module` = 'testtask' and `field` IN ('begin','end');
|
||||
UPDATE `zt_workflowfield` set `control` = 'richtext' WHERE `module` = 'testtask' and `field` = 'desc';
|
||||
|
||||
UPDATE `zt_workflowfield` set `control` = 'datetime' WHERE `module` IN ('testsuite','caselib') and `field` IN ('addedDate','lastEditedDate');
|
||||
UPDATE `zt_workflowfield` set `control` = 'richtext' WHERE `module` = 'testsuite' and `field` = 'desc';
|
||||
|
||||
UPDATE `zt_workflowfield` set `control` = 'datetime' WHERE `module` = 'feedback' and `field` IN ('openedDate','reviewedDate','processedDate','closedDate','editedDate','assignedDate');
|
||||
|
||||
UPDATE `zt_workflowfield` SET `control` = 'datetime' WHERE `module` = 'product' and `field` = 'createdDate';
|
||||
UPDATE `zt_workflowfield` SET `control` = 'date' WHERE `module` = 'productplan' and `field` = 'begin';
|
||||
UPDATE `zt_workflowfield` SET `control` = 'date' WHERE `module` = 'productplan' and `field` = 'end';
|
||||
UPDATE `zt_workflowfield` SET `control` = 'radio' WHERE `module` = 'productplan' and `field` = 'deleted';
|
||||
UPDATE `zt_workflowfield` SET `control` = 'select', `options` = 12 WHERE `module` = 'productplan' and `field` = 'parent';
|
||||
UPDATE `zt_workflowfield` SET `control` = 'date' WHERE `module` = 'release' and `field` = 'date';
|
||||
UPDATE `zt_workflowfield` SET `control` = 'richtext' WHERE `module` = 'release' and `field` = 'desc';
|
||||
UPDATE `zt_workflowfield` SET `control` = 'radio' WHERE `module` = 'release' and `field` = 'deleted';
|
||||
UPDATE `zt_workflowfield` SET `control` = 'datetime' WHERE `module` = 'story' and `field` = 'assignedDate';
|
||||
UPDATE `zt_workflowfield` SET `control` = 'datetime' WHERE `module` = 'story' and `field` = 'lastEditedDate';
|
||||
UPDATE `zt_workflowfield` SET `control` = 'date' WHERE `module` = 'story' and `field` = 'reviewedDate';
|
||||
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';
|
||||
|
||||
ALTER TABLE `zt_workflowdatasource` ADD UNIQUE `code` (`code`);
|
||||
|
||||
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', '', '', '');
|
||||
|
||||
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', '', '', '', '', '', 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';
|
||||
|
||||
@@ -416,7 +416,7 @@ class baseControl
|
||||
$moduleName = basename(dirname(dirname(realpath($viewFile))));
|
||||
$extPath = $this->app->getModuleExtPath('', $moduleName, 'view');
|
||||
|
||||
$checkedOrder = array('site', 'custom', 'vision', 'xuan', 'common');
|
||||
$checkedOrder = array('site', 'saas', 'custom', 'vision', 'xuan', 'common');
|
||||
$fileName = basename($viewFile);
|
||||
foreach($checkedOrder as $checkedType)
|
||||
{
|
||||
@@ -805,6 +805,12 @@ class baseControl
|
||||
$commonActionExtFile = $actionExtPath['custom'] . strtolower($methodName) . '.php';
|
||||
if(file_exists($commonActionExtFile)) $file2Included = $commonActionExtFile;
|
||||
|
||||
if(!empty($actionExtPath['saas']))
|
||||
{
|
||||
$commonActionExtFile = $actionExtPath['saas'] . strtolower($methodName) . '.php';
|
||||
if(file_exists($commonActionExtFile)) $file2Included = $commonActionExtFile;
|
||||
}
|
||||
|
||||
if(!empty($actionExtPath['site']))
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -260,6 +260,7 @@ class baseModel
|
||||
$moduleExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'model');
|
||||
if(!empty($moduleExtPath['site'])) $extensionFile = $moduleExtPath['site'] . 'class/' . $extensionName . '.class.php';
|
||||
if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['custom'] . 'class/' . $extensionName . '.class.php';
|
||||
if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['saas'] . 'class/' . $extensionName . '.class.php';
|
||||
if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['vision'] . 'class/' . $extensionName . '.class.php';
|
||||
if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['xuan'] . 'class/' . $extensionName . '.class.php';
|
||||
if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['common'] . 'class/' . $extensionName . '.class.php';
|
||||
|
||||
@@ -1390,6 +1390,9 @@ class baseRouter
|
||||
|
||||
if($this->checkModuleName($moduleName))
|
||||
{
|
||||
$modulePath = $this->getExtensionRoot() . 'saas' . DS . $moduleName . DS;
|
||||
if(is_dir($modulePath) and (file_exists($modulePath . 'control.php') or file_exists($modulePath . 'model.php'))) return $modulePath;
|
||||
|
||||
/* 1. 最后尝试在定制开发中寻找。 Finally, try to find the module in the custom dir. */
|
||||
$modulePath = $this->getExtensionRoot() . 'custom' . DS . $moduleName . DS;
|
||||
if(is_dir($modulePath) and (file_exists($modulePath . 'control.php') or file_exists($modulePath . 'model.php'))) return $modulePath;
|
||||
@@ -1432,8 +1435,10 @@ class baseRouter
|
||||
*/
|
||||
public function getModuleExtPath($appName, $moduleName, $ext)
|
||||
{
|
||||
$saasExtPath = $this->getExtensionRoot() . 'saas' . DS . $moduleName . DS . 'ext' . DS . $ext . DS;
|
||||
|
||||
/* 检查失败或者extensionLevel为0,直接返回空。If check failed or extensionLevel == 0, return empty array. */
|
||||
if(!$this->checkModuleName($moduleName) or $this->config->framework->extensionLevel == 0) return array();
|
||||
if(!$this->checkModuleName($moduleName) or $this->config->framework->extensionLevel == 0) return array('saas' => $saasExtPath);
|
||||
|
||||
$paths = array();
|
||||
|
||||
@@ -1442,10 +1447,16 @@ class baseRouter
|
||||
$paths['xuan'] = $this->getExtensionRoot() . 'xuan' . DS . $moduleName . DS . 'ext' . DS . $ext . DS;
|
||||
$paths['vision'] = $this->config->vision == 'rnd' ? '' : $this->basePath . 'extension' . DS . $this->config->vision . DS . $moduleName . DS . 'ext' . DS . $ext . DS;
|
||||
$paths['custom'] = $this->getExtensionRoot() . 'custom' . DS . $moduleName . DS . 'ext' . DS . $ext . DS;
|
||||
if($this->config->framework->extensionLevel == 1) return $paths;
|
||||
if($this->config->framework->extensionLevel == 1)
|
||||
{
|
||||
$paths['saas'] = $saasExtPath;
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/* When extensionLevel == 2. */
|
||||
$paths['site'] = empty($this->siteCode) ? '' : $this->getExtensionRoot() . $this->config->edition . DS . $moduleName . DS . 'ext' . DS . '_' . $this->siteCode . DS . $ext . DS;
|
||||
$paths['saas'] = $saasExtPath;
|
||||
|
||||
return $paths;
|
||||
}
|
||||
|
||||
@@ -1494,6 +1505,12 @@ class baseRouter
|
||||
/* 如果扩展目录为空,不包含任何扩展文件。If there's no ext paths return false.*/
|
||||
if(empty($moduleExtPaths)) return false;
|
||||
|
||||
if(!empty( $moduleExtPaths['saas']))
|
||||
{
|
||||
$this->extActionFile = $moduleExtPaths['saas'] . $this->methodName . '.php';
|
||||
if(file_exists($this->extActionFile)) return true;
|
||||
}
|
||||
|
||||
/* 1. 如果extensionLevel == 2,且扩展文件存在,返回该站点扩展文件。 If extensionLevel == 2 and site extensionFile exists, return it. */
|
||||
if($this->config->framework->extensionLevel == 2 and !empty( $moduleExtPaths['site']))
|
||||
{
|
||||
@@ -2322,6 +2339,7 @@ class baseRouter
|
||||
if(!empty($extConfigPath['common'])) $commonExtConfigFiles = helper::ls($extConfigPath['common'], '.php');
|
||||
if(!empty($extConfigPath['xuan'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['xuan'], '.php'));
|
||||
if(!empty($extConfigPath['vision'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['vision'], '.php'));
|
||||
if(!empty($extConfigPath['saas'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['saas'], '.php'));
|
||||
if(!empty($extConfigPath['custom'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['custom'], '.php'));
|
||||
}
|
||||
if($config->framework->extensionLevel == 2 and !empty($extConfigPath['site'])) $siteExtConfigFiles = helper::ls($extConfigPath['site'], '.php');
|
||||
@@ -2427,6 +2445,9 @@ class baseRouter
|
||||
{
|
||||
$path = $moduleName . DS . 'lang' . DS . $this->clientLang . '.php';
|
||||
|
||||
$modulePath = $this->getExtensionRoot() . 'saas' . DS;
|
||||
if(file_exists($modulePath . $path)) return $modulePath . $path;
|
||||
|
||||
/* 1. 如果通用版本里有此模块,优先使用。 If module is in the open edition, use it. */
|
||||
$modulePath = $this->getModuleRoot($appName);
|
||||
if(file_exists($modulePath . $path)) return $modulePath . $path;
|
||||
@@ -2489,6 +2510,7 @@ class baseRouter
|
||||
if(!empty($extLangPath['xuan'])) $commonExtLangFiles = array_merge($commonExtLangFiles, helper::ls($extLangPath['xuan'] . $this->clientLang, '.php'));
|
||||
if(!empty($extLangPath['vision'])) $commonExtLangFiles = array_merge($commonExtLangFiles, helper::ls($extLangPath['vision'] . $this->clientLang, '.php'));
|
||||
if(!empty($extLangPath['custom'])) $commonExtLangFiles = array_merge($commonExtLangFiles, helper::ls($extLangPath['custom'] . $this->clientLang, '.php'));
|
||||
if(!empty($extLangPath['saas'])) $commonExtLangFiles = array_merge($commonExtLangFiles, helper::ls($extLangPath['saas'] . $this->clientLang, '.php'));
|
||||
}
|
||||
if($this->config->framework->extensionLevel == 2 and !empty($extLangPath['site'])) $siteExtLangFiles = helper::ls($extLangPath['site'] . $this->clientLang, '.php');
|
||||
$extLangFiles = array_merge($commonExtLangFiles, $siteExtLangFiles);
|
||||
|
||||
@@ -86,7 +86,7 @@ class control extends baseControl
|
||||
|
||||
/**
|
||||
* Det default priv by workflow.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
@@ -197,6 +197,7 @@ class control extends baseControl
|
||||
$commonExtViewFile = $viewExtPath['common'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
|
||||
$xuanExtViewFile = $viewExtPath['xuan'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
|
||||
$visionExtViewFile = $viewExtPath['vision'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
|
||||
$saasExtViewFile = $viewExtPath['saas'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
|
||||
$customExtViewFile = $viewExtPath['custom'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
|
||||
$siteExtViewFile = empty($viewExtPath['site']) ? '' : $viewExtPath['site'] . $this->devicePrefix . $methodName . ".{$viewType}.php";
|
||||
|
||||
@@ -217,6 +218,10 @@ class control extends baseControl
|
||||
{
|
||||
$viewFile = $xuanExtViewFile;
|
||||
}
|
||||
else if(file_exists($saasExtViewFile))
|
||||
{
|
||||
$viewFile = $saasExtViewFile;
|
||||
}
|
||||
else if(file_exists($commonExtViewFile))
|
||||
{
|
||||
$viewFile = $commonExtViewFile;
|
||||
@@ -235,10 +240,11 @@ class control extends baseControl
|
||||
$commonExtHookFiles = glob($viewExtPath['vision'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
|
||||
}
|
||||
$xuanExtHookFiles = glob($viewExtPath['xuan'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
|
||||
$saasExtHookFiles = glob($viewExtPath['saas'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
|
||||
$customExtHookFiles = glob($viewExtPath['custom'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
|
||||
|
||||
$siteExtHookFiles = empty($viewExtPath['site']) ? '' : glob($viewExtPath['site'] . $this->devicePrefix . $methodName . ".*.{$viewType}.hook.php");
|
||||
$extHookFiles = array_merge((array)$commonExtHookFiles, (array)$xuanExtHookFiles, (array)$customExtHookFiles, (array)$siteExtHookFiles);
|
||||
$extHookFiles = array_merge((array)$commonExtHookFiles, (array)$xuanExtHookFiles, (array)$saasExtHookFiles, (array)$customExtHookFiles, (array)$siteExtHookFiles);
|
||||
}
|
||||
|
||||
if(!empty($extHookFiles)) return array('viewFile' => $viewFile, 'hookFiles' => $extHookFiles);
|
||||
@@ -320,7 +326,7 @@ class control extends baseControl
|
||||
if(!isset($this->config->bizVersion)) return false;
|
||||
|
||||
$moduleName = $this->moduleName;
|
||||
if($moduleName == 'bug' || $moduleName == 'feedback') return $this->$moduleName->buildOperateMenu($object, $type);
|
||||
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);
|
||||
@@ -342,9 +348,9 @@ class control extends baseControl
|
||||
}
|
||||
|
||||
/**
|
||||
* Set workflow export fields
|
||||
*
|
||||
* @param array $fields
|
||||
* Set workflow export fields
|
||||
*
|
||||
* @param array $fields
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
|
||||
@@ -83,7 +83,15 @@ class model extends baseModel
|
||||
if(isset($this->config->bizVersion))
|
||||
{
|
||||
static $actions;
|
||||
if(empty($actions)) $actions = $this->dao->select('*')->from(TABLE_WORKFLOWACTION)->where('module')->eq($moduleName)->andWhere('buildin')->eq('1')->andWhere('status')->eq('enable')->fetchAll('action');
|
||||
if(empty($actions))
|
||||
{
|
||||
$actions = $this->dao->select('*')->from(TABLE_WORKFLOWACTION)
|
||||
->where('module')->eq($moduleName)
|
||||
->andWhere('buildin')->eq('1')
|
||||
->andWhere('status')->eq('enable')
|
||||
->beginIF(!empty($this->config->vision))->andWhere('vision')->eq($this->config->vision)->fi()
|
||||
->fetchAll('action');
|
||||
}
|
||||
}
|
||||
|
||||
$enabled = true;
|
||||
@@ -133,7 +141,16 @@ class model extends baseModel
|
||||
if(strpos($module, '.') !== false) list($appName, $moduleName) = explode('.', $module);
|
||||
|
||||
static $actions;
|
||||
if(empty($actions)) $actions = $this->dao->select('*')->from(TABLE_WORKFLOWACTION)->where('module')->eq($moduleName)->andWhere('buildin')->eq('0')->andWhere('status')->eq('enable')->orderBy('order_asc')->fetchAll();
|
||||
if(empty($actions))
|
||||
{
|
||||
$actions = $this->dao->select('*')->from(TABLE_WORKFLOWACTION)
|
||||
->where('module')->eq($moduleName)
|
||||
->andWhere('buildin')->eq('0')
|
||||
->andWhere('status')->eq('enable')
|
||||
->beginIF(!empty($this->config->vision))->andWhere('vision')->eq($this->config->vision)->fi()
|
||||
->orderBy('order_asc')
|
||||
->fetchAll();
|
||||
}
|
||||
|
||||
$menu = '';
|
||||
if($show)
|
||||
|
||||
@@ -327,6 +327,7 @@ class router extends baseRouter
|
||||
if(!empty($extConfigPath['common'])) $commonExtConfigFiles = helper::ls($extConfigPath['common'], '.php');
|
||||
if(!empty($extConfigPath['xuan'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['xuan'], '.php'));
|
||||
if(!empty($extConfigPath['vision'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['vision'], '.php'));
|
||||
if(!empty($extConfigPath['saas'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['saas'], '.php'));
|
||||
if(!empty($extConfigPath['custom'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['custom'], '.php'));
|
||||
}
|
||||
if($config->framework->extensionLevel == 2 and !empty($extConfigPath['site'])) $siteExtConfigFiles = helper::ls($extConfigPath['site'], '.php');
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -12,6 +12,50 @@
|
||||
?>
|
||||
<?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'");?>
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -71,6 +71,7 @@ $config->bug->search['fields']['resolvedBy'] = $lang->bug->resolvedBy;
|
||||
|
||||
$config->bug->search['fields']['status'] = $lang->bug->status;
|
||||
$config->bug->search['fields']['confirmed'] = $lang->bug->confirmed;
|
||||
$config->bug->search['fields']['story'] = $lang->bug->story;
|
||||
|
||||
if($config->systemMode == 'new') $config->bug->search['fields']['project'] = $lang->bug->project;
|
||||
$config->bug->search['fields']['product'] = $lang->bug->product;
|
||||
@@ -116,6 +117,7 @@ $config->bug->search['params']['resolvedBy'] = array('operator' => '=',
|
||||
|
||||
$config->bug->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->bug->statusList);
|
||||
$config->bug->search['params']['confirmed'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->bug->confirmedList);
|
||||
$config->bug->search['params']['story'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
|
||||
|
||||
if($config->systemMode == 'new') $config->bug->search['params']['project'] = array('operator' => '=', 'control' => 'select', 'values' => '');
|
||||
$config->bug->search['params']['product'] = array('operator' => '=', 'control' => 'select', 'values' => '');
|
||||
|
||||
+23
-3
@@ -2730,6 +2730,26 @@ class bugModel extends model
|
||||
/* Fix bug #2878. */
|
||||
if(strpos($bugQuery, ' `resolvedDate` ') !== false) $bugQuery = str_replace(' `resolvedDate` ', " `resolvedDate` != '0000-00-00 00:00:00' AND `resolvedDate` ", $bugQuery);
|
||||
if(strpos($bugQuery, ' `closedDate` ') !== false) $bugQuery = str_replace(' `closedDate` ', " `closedDate` != '0000-00-00 00:00:00' AND `closedDate` ", $bugQuery);
|
||||
if(strpos($bugQuery, ' `story` ') !== false)
|
||||
{
|
||||
preg_match_all("/`story`[ ]+(NOT *)?LIKE[ ]+'%([^%]*)%'/Ui", $bugQuery, $out);
|
||||
if(!empty($out[2]))
|
||||
{
|
||||
foreach($out[2] as $searchValue)
|
||||
{
|
||||
$story = $this->dao->select('id')->from(TABLE_STORY)->alias('t1')
|
||||
->leftJoin(TABLE_STORYSPEC)->alias('t2')->on('t1.id=t2.story')
|
||||
->where('t1.title')->like("%$searchValue%")
|
||||
->orWhere('t1.keywords')->like("%$searchValue%")
|
||||
->orWhere('t2.spec')->like("%$searchValue%")
|
||||
->orWhere('t2.verify')->like("%$searchValue%")
|
||||
->fetchPairs('id');
|
||||
|
||||
$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()
|
||||
@@ -3234,9 +3254,9 @@ class bugModel extends model
|
||||
|
||||
/**
|
||||
* Build bug menu.
|
||||
*
|
||||
* @param object $bug
|
||||
* @param string $type
|
||||
*
|
||||
* @param object $bug
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 = '导入用例';
|
||||
|
||||
@@ -595,4 +595,65 @@ class caselibModel extends model
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build case lib menu.
|
||||
*
|
||||
* @param object $object
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildOperateMenu($object, $type = 'view')
|
||||
{
|
||||
$function = 'buildOperate' . ucfirst($type) . 'Menu';
|
||||
return $this->$function($object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build case lib view menu.
|
||||
*
|
||||
* @param object $lib
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildOperateViewMenu($lib)
|
||||
{
|
||||
if($lib->deleted) return '';
|
||||
|
||||
$menu = '';
|
||||
$params = "libID=$lib->id";
|
||||
$menu .= $this->buildFlowMenu('caselib', $lib, 'view', 'direct');
|
||||
$menu .= "<div class='divider'></div>";
|
||||
$menu .= $this->buildMenu('caselib', 'edit', $params, $lib, 'view');
|
||||
$menu .= $this->buildMenu('caselib', 'delete', $params, $lib, 'view', 'trash', 'hiddenwin');
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build case lib browse menu.
|
||||
*
|
||||
* @param object $case
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildOperateBrowseMenu($case)
|
||||
{
|
||||
$menu = '';
|
||||
$params = "caseID=$case->id";
|
||||
|
||||
if($this->config->testcase->needReview || !empty($this->config->testcase->forceReview))
|
||||
{
|
||||
$menu .= $this->buildMenu('testcase', 'review', $params, $case, 'browse', 'glasses', '', 'iframe');
|
||||
}
|
||||
$menu .= $this->buildMenu('testcase', 'edit', $params, $case, 'browse');
|
||||
if(common::hasPriv('testcase', 'delete'))
|
||||
{
|
||||
$deleteURL = helper::createLink('testcase', 'delete', "$params&confirm=yes");
|
||||
$menu .= html::a("javascript:ajaxDelete(\"$deleteURL\", \"caseList\", confirmDelete)", '<i class="icon icon-trash"></i>', '', "title='{$this->lang->testcase->delete}' class='btn'");
|
||||
}
|
||||
|
||||
return $menu;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,15 +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
|
||||
if($config->testcase->needReview or !empty($config->testcase->forceReview)) common::printIcon('testcase', 'review', "caseID=$case->id", $case, 'list', 'glasses', '', 'iframe');
|
||||
common::printIcon('testcase', 'edit', "caseID=$case->id", $case, 'list');
|
||||
if(common::hasPriv('testcase', 'delete'))
|
||||
{
|
||||
$deleteURL = $this->createLink('testcase', 'delete', "caseID=$case->id&confirm=yes");
|
||||
echo html::a("javascript:ajaxDelete(\"$deleteURL\", \"caseList\", confirmDelete)", '<i class="icon icon-trash"></i>', '', "title='{$lang->testcase->delete}' class='btn'");
|
||||
}
|
||||
?>
|
||||
<?php echo $this->buildOperateMenu($case, 'browse');?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
|
||||
@@ -37,15 +37,9 @@
|
||||
<div class='main-actions'>
|
||||
<nav class="container"></nav>
|
||||
<div class="btn-toolbar">
|
||||
<?php
|
||||
common::printBack($browseLink);
|
||||
if(!$lib->deleted)
|
||||
{
|
||||
echo "<div class='divider'></div>";
|
||||
common::printIcon('caselib', 'edit', "libID=$lib->id");
|
||||
common::printIcon('caselib', 'delete', "libID=$lib->id", '', 'button', 'trash', 'hiddenwin');
|
||||
}
|
||||
?>
|
||||
<?php common::printBack($browseLink);?>
|
||||
<?php echo "<div class='divider'></div>";?>
|
||||
<?php echo $this->buildOperateMenu($lib, 'view');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -48,8 +48,8 @@ $config->custom->fieldList['release']['create'] = 'desc';
|
||||
$config->custom->fieldList['release']['edit'] = 'desc';
|
||||
$config->custom->fieldList['execution']['create'] = 'days,desc,PO,PM,QD,RD';
|
||||
$config->custom->fieldList['execution']['edit'] = 'days,desc,PO,PM,QD,RD';
|
||||
$config->custom->fieldList['task']['create'] = 'story,pri,estimate,desc,estStarted,deadline';
|
||||
$config->custom->fieldList['task']['edit'] = 'pri,estimate,estStarted,deadline';
|
||||
$config->custom->fieldList['task']['create'] = 'module,story,pri,estimate,desc,estStarted,deadline';
|
||||
$config->custom->fieldList['task']['edit'] = 'module,pri,estimate,estStarted,deadline';
|
||||
$config->custom->fieldList['task']['finish'] = 'comment';
|
||||
$config->custom->fieldList['task']['activate'] = 'assignedTo,comment';
|
||||
$config->custom->fieldList['build'] = 'scmPath,filePath,desc';
|
||||
|
||||
@@ -251,7 +251,9 @@ class customModel extends model
|
||||
foreach($item['subMenu'] as $subMenu)
|
||||
{
|
||||
if(!isset($subMenu['link']) or strpos($subMenu['link'], '|') === false) continue;
|
||||
list($subLabel, $module, $method, $vars) = explode('|', $subMenu['link']);
|
||||
list($subLabel, $module, $method) = explode('|', $subMenu['link']);
|
||||
if(count(explode('|', $subMenu['link'])) > 3) list($subLabel, $module, $method, $vars) = explode('|', $subMenu['link']);
|
||||
|
||||
$hasPriv = commonModel::hasPriv($module, $method);
|
||||
if($hasPriv) break;
|
||||
}
|
||||
|
||||
@@ -3148,7 +3148,16 @@ class execution extends control
|
||||
}
|
||||
|
||||
$projectExecutions = array();
|
||||
foreach($orderedExecutions as $execution) $projectExecutions[$execution->project][] = $execution;
|
||||
$parentIdList = array();
|
||||
foreach($orderedExecutions as $execution)
|
||||
{
|
||||
$projectExecutions[$execution->project][] = $execution;
|
||||
if($execution->type != 'stage') continue;
|
||||
if($execution->grade == 2 and $execution->project != $execution->parent) $parentIdList[$execution->parent] = $execution->parent;
|
||||
}
|
||||
|
||||
$parents = array();
|
||||
if($parentIdList) $parents = $this->execution->getByIdList($parentIdList);
|
||||
|
||||
$this->view->link = $this->execution->getLink($module, $method, $extra);
|
||||
$this->view->module = $module;
|
||||
@@ -3157,6 +3166,7 @@ class execution extends control
|
||||
$this->view->extra = $extra;
|
||||
$this->view->projects = $projectPairs;
|
||||
$this->view->executions = $projectExecutions;
|
||||
$this->view->parents = $parents;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
|
||||
@@ -328,6 +328,10 @@ if(!window.kanbanDropRules)
|
||||
{
|
||||
backlog: ['ready', 'backlog'],
|
||||
ready: ['backlog', 'ready'],
|
||||
tested: ['verified'],
|
||||
verified: ['tested', 'released'],
|
||||
released: ['verified', 'closed'],
|
||||
closed: ['released'],
|
||||
},
|
||||
bug:
|
||||
{
|
||||
@@ -957,7 +961,12 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
|
||||
/* Story lane. */
|
||||
if(cardType == 'story')
|
||||
{
|
||||
if(toColType == 'ready' || toColType == 'backlog')
|
||||
if(toColType == 'closed' && priv.canCloseStory)
|
||||
{
|
||||
var link = createLink('story', 'close', 'storyID=' + objectID, '', true);
|
||||
showIframe = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(toColType == 'ready' && typeof(reviewStoryParis[objectID]) != 'undefined')
|
||||
{
|
||||
|
||||
@@ -480,6 +480,10 @@ if(!window.kanbanDropRules)
|
||||
{
|
||||
backlog: ['ready'],
|
||||
ready: ['backlog'],
|
||||
tested: ['verified'],
|
||||
verified: ['tested', 'released'],
|
||||
released: ['verified', 'closed'],
|
||||
closed: ['released'],
|
||||
},
|
||||
bug:
|
||||
{
|
||||
@@ -495,7 +499,7 @@ if(!window.kanbanDropRules)
|
||||
{
|
||||
'wait': ['developing', 'developed', 'canceled', 'closed'],
|
||||
'developing': ['developed', 'pause', 'canceled'],
|
||||
'developed': ['closed'],
|
||||
'developed': ['developing', 'closed'],
|
||||
'pause': ['developing'],
|
||||
'canceled': ['developing'],
|
||||
'closed': ['developing'],
|
||||
@@ -683,7 +687,12 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
|
||||
/* Story lane. */
|
||||
if(cardType == 'story')
|
||||
{
|
||||
if(toColType == 'ready' || toColType == 'backlog')
|
||||
if(toColType == 'closed' && priv.canCloseStory)
|
||||
{
|
||||
var link = createLink('story', 'close', 'storyID=' + objectID, '', true);
|
||||
showIframe = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(toColType == 'ready' && typeof(reviewStoryParis[objectID]) != 'undefined')
|
||||
{
|
||||
@@ -706,7 +715,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
|
||||
updateKanban(browseType, kanbanGroup[groupBy]);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2791,15 +2791,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))
|
||||
@@ -2819,8 +2874,9 @@ class executionModel extends model
|
||||
->where('execution')->in(array_keys($executions))
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('parent')->ge('0')
|
||||
->andWhere('status')->eq('done')
|
||||
->andWhere('status', true)->eq('done')
|
||||
->orWhere('status')->eq('closed')
|
||||
->markRight(1)
|
||||
->groupBy('execution')
|
||||
->fetchAll('execution');
|
||||
$storyPoints = $this->dao->select('t1.project, sum(t2.estimate) AS `storyPoint`')->from(TABLE_PROJECTSTORY)->alias('t1')
|
||||
@@ -2851,8 +2907,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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,7 +46,12 @@ foreach($executions as $projectID => $projectExecutions)
|
||||
if($execution->status != 'done' and $execution->status != 'closed' and ($execution->PM == $this->app->user->account or isset($execution->teams[$this->app->user->account]))) $executionCounts[$projectID]['myExecution'] ++;
|
||||
if($execution->status != 'done' and $execution->status != 'closed' and $execution->PM != $this->app->user->account and !isset($execution->teams[$this->app->user->account])) $executionCounts[$projectID]['others'] ++;
|
||||
if($execution->status == 'done' or $execution->status == 'closed') $executionCounts[$projectID]['closed'] ++;
|
||||
$executionNames[] = $execution->name;
|
||||
$onlyChildStage = $execution->grade == 2 and $execution->project != $execution->parent;
|
||||
$executionNames[$execution->id] = $execution->name;
|
||||
if($onlyChildStage and isset($parents[$execution->parent]))
|
||||
{
|
||||
$executionNames[$execution->id] = $parents[$execution->parent]->name . '/' . $execution->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
$executionsPinYin = common::convert2Pinyin($executionNames);
|
||||
@@ -77,7 +82,7 @@ foreach($executions as $projectID => $projectExecutions)
|
||||
$selected = $execution->id == $executionID ? 'selected' : '';
|
||||
if($execution->status != 'done' and $execution->status != 'closed' and ($execution->PM == $this->app->user->account or isset($execution->teams[$this->app->user->account])))
|
||||
{
|
||||
$myExecutionsHtml .= '<li>' . html::a(sprintf($link, $execution->id), $execution->name, '', "class='$selected clickable' title='{$execution->name}' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '</li>';
|
||||
$myExecutionsHtml .= '<li>' . html::a(sprintf($link, $execution->id), $executionNames[$execution->id], '', "class='$selected clickable' title='{$execution->name}' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '</li>';
|
||||
|
||||
if($selected == 'selected') $tabActive = 'myExecution';
|
||||
|
||||
@@ -85,7 +90,7 @@ foreach($executions as $projectID => $projectExecutions)
|
||||
}
|
||||
else if($execution->status != 'done' and $execution->status != 'closed' and $execution->PM != $this->app->user->account and !isset($execution->teams[$this->app->user->account]))
|
||||
{
|
||||
$normalExecutionsHtml .= '<li>' . html::a(sprintf($link, $execution->id), $execution->name, '', "class='$selected clickable' title='{$execution->name}' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '</li>';
|
||||
$normalExecutionsHtml .= '<li>' . html::a(sprintf($link, $execution->id), $executionNames[$execution->id], '', "class='$selected clickable' title='{$execution->name}' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '</li>';
|
||||
|
||||
if($selected == 'selected') $tabActive = 'other';
|
||||
|
||||
@@ -93,7 +98,7 @@ foreach($executions as $projectID => $projectExecutions)
|
||||
}
|
||||
else if($execution->status == 'done' or $execution->status == 'closed')
|
||||
{
|
||||
$closedExecutionsHtml .= '<li>' . html::a(sprintf($link, $execution->id), $execution->name, '', "class='$selected clickable' title='$execution->name' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '</li>';
|
||||
$closedExecutionsHtml .= '<li>' . html::a(sprintf($link, $execution->id), $executionNames[$execution->id], '', "class='$selected clickable' title='$execution->name' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '</li>';
|
||||
|
||||
if($selected == 'selected') $tabActive = 'closed';
|
||||
}
|
||||
@@ -171,7 +176,7 @@ $(function()
|
||||
$('li.has-list div.hide-in-search').removeClass('hidden');
|
||||
$('.nav-tabs li.active').find('span').show();
|
||||
}
|
||||
|
||||
|
||||
if($('.form-control.search-input').val().length > 0)
|
||||
{
|
||||
$('#closed').attr("hidden", false);
|
||||
@@ -191,7 +196,7 @@ $(function()
|
||||
$('#closed').attr("hidden", true);
|
||||
$('#gray-line').attr("hidden", true);
|
||||
}
|
||||
|
||||
|
||||
var listItem = $(this).find('.has-list');
|
||||
listItem.each(function ()
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<div class='btn-toolbar pull-left'>
|
||||
<?php
|
||||
$weekend = ($type == 'noweekend') ? 'withweekend' : "noweekend";
|
||||
common::printLink('execution', 'computeBurn', 'reload=yes', '<i class="icon icon-refresh"></i> ' . $lang->execution->computeBurn, 'hiddenwin', "title='{$lang->execution->computeBurn}{$lang->execution->burn}' class='btn btn-primary' id='computeBurn'");
|
||||
common::printLink('execution', 'computeBurn', 'reload=yes', '<i class="icon icon-refresh"></i> ' . $lang->execution->computeBurn, 'hiddenwin', "title='{$lang->execution->computeBurn}' class='btn btn-primary' id='computeBurn'");
|
||||
echo '<div class="space"></div>';
|
||||
echo html::a($this->createLink('execution', 'burn', "executionID=$executionID&type=$weekend&interval=$interval"), $lang->execution->$weekend, '', "class='btn btn-link'");
|
||||
if(common::canModify('execution', $execution)) common::printLink('execution', 'fixFirst', "execution=$execution->id", $lang->execution->fixFirst, '', "class='btn btn-link iframe' data-width='700'");
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -105,6 +105,7 @@ js::set('priv',
|
||||
'canEditStory' => common::hasPriv('story', 'edit'),
|
||||
'canDeleteStory' => common::hasPriv('story', 'delete'),
|
||||
'canChangeStory' => common::hasPriv('story', 'change'),
|
||||
'canCloseStory' => common::hasPriv('story', 'close'),
|
||||
'canUnlinkStory' => common::hasPriv('execution', 'unlinkStory'),
|
||||
)
|
||||
);
|
||||
|
||||
@@ -193,7 +193,8 @@ js::set('priv',
|
||||
'canStartTask' => common::hasPriv('task', 'start'),
|
||||
'canAssignBug' => common::hasPriv('bug', 'assignto'),
|
||||
'canConfirmBug' => common::hasPriv('bug', 'confirmBug'),
|
||||
'canActivateBug' => common::hasPriv('bug', 'activate')
|
||||
'canActivateBug' => common::hasPriv('bug', 'activate'),
|
||||
'canCloseStory' => common::hasPriv('story', 'close')
|
||||
)
|
||||
);
|
||||
?>
|
||||
|
||||
@@ -1320,8 +1320,14 @@ class kanban extends control
|
||||
{
|
||||
$region = $this->kanban->getRegionByID($regionID);
|
||||
|
||||
$cards = $this->kanban->getCardsByObject('region', $regionID, 1);
|
||||
foreach($this->config->kanban->fromType as $fromType)
|
||||
{
|
||||
$cards = $this->kanban->getImportedCards($region->kanban, $cards, $fromType, 1);
|
||||
}
|
||||
|
||||
$this->view->kanban = $this->kanban->getByID($region->kanban);
|
||||
$this->view->cards = $this->kanban->getCardsByObject('region', $regionID, 1);
|
||||
$this->view->cards = $cards;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter|nodeleted');
|
||||
$this->view->userIdPairs = $this->user->getPairs('noletter|nodeleted|showid');
|
||||
$this->view->usersAvatar = $this->user->getAvatarPairs();
|
||||
@@ -1374,13 +1380,20 @@ class kanban extends control
|
||||
*/
|
||||
public function deleteCard($cardID, $confirm = 'no')
|
||||
{
|
||||
$card = $this->kanban->getCardByID($cardID);
|
||||
if($confirm == 'no')
|
||||
{
|
||||
return print(js::confirm($this->lang->kanbancard->confirmDelete, $this->createLink('kanban', 'deleteCard', "cardID=$cardID&confirm=yes")));
|
||||
$confirmTip = $card->fromType == '' ? $this->lang->kanbancard->confirmDelete : $this->lang->kanbancard->confirmRemove;
|
||||
return print(js::confirm($confirmTip, $this->createLink('kanban', 'deleteCard', "cardID=$cardID&confirm=yes")));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->kanban->delete(TABLE_KANBANCARD, $cardID);
|
||||
if($card->fromType == '') $this->kanban->delete(TABLE_KANBANCARD, $cardID);
|
||||
if($card->fromType != '')
|
||||
{
|
||||
$this->dao->delete()->from(TABLE_KANBANCARD)->where('id')->eq($cardID)->exec();
|
||||
$this->loadModel('action')->create('kanbancard', $cardID, 'Deleted', '', $cardID);
|
||||
}
|
||||
|
||||
if(isonlybody()) return print(js::reload('parent.parent'));
|
||||
return print(js::reload('parent'));
|
||||
@@ -1663,6 +1676,20 @@ class kanban extends control
|
||||
->andWhere('`column`')->eq($toColID)
|
||||
->exec();
|
||||
|
||||
$toColumn = $this->kanban->getColumnByID($toColID);
|
||||
if($toColumn->laneType == 'story' and in_array($toColumn->type, array('tested', 'verified', 'released', 'closed')))
|
||||
{
|
||||
$data = new stdclass();
|
||||
$data->stage = $toColumn->type;
|
||||
if($toColumn->type == 'released')
|
||||
{
|
||||
$fromColumn = $this->kanban->getColumnByID($fromColID);
|
||||
if($fromColumn->type == 'closed') $data->status = 'active';
|
||||
}
|
||||
$this->dao->update(TABLE_STORY)->data($data)->where('id')->eq($cardID)->exec();
|
||||
$this->dao->update(TABLE_STORYSTAGE)->set('stage')->eq($toColumn->type)->where('story')->eq($cardID)->exec();
|
||||
}
|
||||
|
||||
$kanbanGroup = $regionID == 0 ? $this->kanban->getExecutionKanban($executionID, $browseType, $groupBy) : $this->kanban->getRDKanban($executionID, $browseType, $orderBy, $regionID, $groupBy);
|
||||
echo json_encode($kanbanGroup);
|
||||
}
|
||||
|
||||
@@ -121,13 +121,13 @@
|
||||
.label-closed, .label-terminate {background: #e5e5e5 !important; color: #b8b8b8;}
|
||||
.label-deleted {background: #ff5d5d !important; color: #fff;}
|
||||
.label-normal {background: #e1e8d9 !important; color: #9abe76;}
|
||||
.kanban-item > .kanban-card > .execInfo > .user, .kanban-item > .kanban-card > .releaseInfo > .user, .kanban-item > .kanban-card > .productplanInfo > .user {position: absolute; right: 13px; bottom: 1px}
|
||||
.kanban-item > .kanban-card > .execInfo > .user, .kanban-item > .kanban-card > .releaseInfo > .user, .kanban-item > .kanban-card > .productplanInfo > .user {float:right}
|
||||
.kanban-item > .kanban-card > .execInfo > .user > .avatar, .kanban-item > .kanban-card > .releaseInfo > .user > .avatar, .kanban-item > .kanban-card > .productplanInfo > .user > .avatar {display: inline-block; width: 24px; height: 24px; line-height: 24px; margin-right: 0px; margin-left: 2px}
|
||||
.kanban-card .releaseTitle .icon, .kanban-card .title .icon, .kanban-card .productplanTitle .icon, .kanban-card .title .icon, .kanban-card .buildTitle .icon{padding-right: 5px;}
|
||||
.kanban-card .label-finish {margin-right: 7px; margin-top: -1px; padding: 3px 5px; float: left; background-color:#2a5f29;}
|
||||
.kanban-card .releaseTitle, .kanban-card .productplanTitle {width: 100%; float: left;}
|
||||
|
||||
.progress-box {display: flex; flex-direction: row; margin-top: 10px;}
|
||||
.progress-box {width:100%; display: flex; flex-direction: row; margin-top: 10px;}
|
||||
.progress {flex: auto; margin: 5px auto 5px;}
|
||||
.progress-number {padding-left: 5px;}
|
||||
|
||||
|
||||
+89
-73
@@ -278,6 +278,22 @@ function renderKanbanItem(item, $item)
|
||||
var whiteStyle = null;
|
||||
if(item.color == '#2a5f29' || item.color == '#b10b0b' || item.color == '#cfa227') whiteStyle = 'style="color:#FFFFFF"';
|
||||
|
||||
var privs = item.actions;
|
||||
var printMoreBtn = (privs.includes('editCard') || privs.includes('archiveCard') || privs.includes('copyCard') || privs.includes('deleteCard') || privs.includes('moveCard') || privs.includes('setCardColor'));
|
||||
var $actions = $item.children('.actions');
|
||||
var $title = $item.children('.title');
|
||||
if(printMoreBtn && !$actions.length)
|
||||
{
|
||||
$(
|
||||
[
|
||||
'<div class="actions" title="' + kanbanLang.more + '">',
|
||||
'<a data-contextmenu="card"' + whiteStyle + 'data-id="' + item.id + '">',
|
||||
'<i class="icon icon-ellipsis-v"></i>',
|
||||
'</a>',
|
||||
'</div>'
|
||||
].join('')).appendTo($item);
|
||||
}
|
||||
|
||||
if(item.fromType == 'execution')
|
||||
{
|
||||
renderExecutionItem(item, $item);
|
||||
@@ -296,53 +312,13 @@ function renderKanbanItem(item, $item)
|
||||
}
|
||||
else
|
||||
{
|
||||
var $title = $item.children('.title');
|
||||
var privs = item.actions;
|
||||
var printMoreBtn = (privs.includes('editCard') || privs.includes('archiveCard') || privs.includes('copyCard') || privs.includes('deleteCard') || privs.includes('moveCard') || privs.includes('setCardColor'));
|
||||
|
||||
if(privs.includes('sortCard')) $item.parent().addClass('sort');
|
||||
if(!$title.length)
|
||||
{
|
||||
$('<div class="label label-finish">' + kanbanLang.finished + '</div>').appendTo($item);
|
||||
if(privs.includes('viewCard')) $title = $('<a class="title iframe" data-toggle="modal" data-width="80%"></a>').appendTo($item).attr('href', createLink('kanban', 'viewCard', 'cardID=' + item.id, '', true));
|
||||
if(!privs.includes('viewCard')) $title = $('<p class="title"></p>').appendTo($item);
|
||||
}
|
||||
$title.text(item.name).attr('title', item.name);
|
||||
|
||||
if(kanban.performable == 1 && item.status == 'done' )
|
||||
{
|
||||
var finishColor = '#2a5f29';
|
||||
if(item.color == '#2a5f29') finishColor = '#FFFFFF';
|
||||
$title.text(item.name).css('color', finishColor);
|
||||
$item.children('.label-finish').show();
|
||||
if(item.color == '#2a5f29')
|
||||
{
|
||||
$item.children('.label-finish').css({'background-color':'#FFFFFF','color':'#2a5f29'});
|
||||
}
|
||||
else
|
||||
{
|
||||
$item.children('.label-finish').css({'background-color':'','color':'#FFFFFF'});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$title.text(item.name).css('color', '');
|
||||
$item.children('.label-finish').hide();
|
||||
}
|
||||
|
||||
var $actions = $item.children('.actions');
|
||||
if(printMoreBtn && !$actions.length)
|
||||
{
|
||||
$(
|
||||
[
|
||||
'<div class="actions" title="' + kanbanLang.more + '">',
|
||||
'<a data-contextmenu="card"' + whiteStyle + 'data-id="' + item.id + '">',
|
||||
'<i class="icon icon-ellipsis-v"></i>',
|
||||
'</a>',
|
||||
'</div>'
|
||||
].join('')).appendTo($item);
|
||||
}
|
||||
|
||||
var $info = $item.children('.info');
|
||||
if(!$info.length) $info = $(
|
||||
[
|
||||
@@ -353,11 +329,6 @@ function renderKanbanItem(item, $item)
|
||||
'<div class="user"></div>',
|
||||
'</div>'
|
||||
].join('')).appendTo($item);
|
||||
if(kanban.performable == 1)
|
||||
{
|
||||
var $progress = $item.children('.progress-box');
|
||||
if(!$progress.length) $progress = $('<div class="progress-box"><div class="progress"><div class="progress-bar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: ' + item.progress + '%;"></div></div><div class="progress-number">' + item.progress + '%</div></div>').appendTo($item);
|
||||
}
|
||||
|
||||
$item.data('card', item);
|
||||
|
||||
@@ -367,15 +338,6 @@ function renderKanbanItem(item, $item)
|
||||
$info.children('.pri')
|
||||
.attr('class', 'pri label-pri label-pri-' + item.pri)
|
||||
.text(item.pri);
|
||||
if(kanban.performable == 1)
|
||||
{
|
||||
$progress.find('.progress-bar').css('width', item.progress + '%');
|
||||
$progress.find('.progress-number').html(item.progress + '%');
|
||||
}
|
||||
|
||||
$item.css('background-color', item.color);
|
||||
$item.toggleClass('has-color', item.color != '#fff' && item.color != '');
|
||||
$item.find('.info > .label-light').css('background-color', item.color);
|
||||
|
||||
var $time = $info.children('.time');
|
||||
if(item.end == '0000-00-00' && item.begin == '0000-00-00')
|
||||
@@ -413,6 +375,41 @@ function renderKanbanItem(item, $item)
|
||||
for(i = 0; i < assignedTo.length; i++) title.push(users[assignedTo[i]]);
|
||||
$user.html(renderUsersAvatar(assignedTo, item.id)).attr('title', title);
|
||||
}
|
||||
|
||||
if(kanban.performable == 1)
|
||||
{
|
||||
var $progress = $item.children('.progress-box');
|
||||
if(!$progress.length) $progress = $('<div class="progress-box"><div class="progress"><div class="progress-bar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: ' + item.progress + '%;"></div></div><div class="progress-number">' + item.progress + '%</div></div>').appendTo($item);
|
||||
$progress.find('.progress-bar').css('width', item.progress + '%');
|
||||
$progress.find('.progress-number').html(item.progress + '%');
|
||||
}
|
||||
$item.css('background-color', item.color);
|
||||
$item.toggleClass('has-color', item.color != '#fff' && item.color != '');
|
||||
$item.find('.info > .label-light').css('background-color', item.color);
|
||||
|
||||
$title = item.fromType == 'execution' ? $item.children('.header').children('.executionName').children('.title') : $item.children('.title');
|
||||
if(!$title.children('.label-finish').length) $title.prepend('<div class="label label-finish">' + kanbanLang.finished + '</div>');
|
||||
var name = item.title ? item.title : item.name;
|
||||
if(kanban.performable == 1 && item.status == 'done' )
|
||||
{
|
||||
var finishColor = '#2a5f29';
|
||||
if(item.color == '#2a5f29') finishColor = '#FFFFFF';
|
||||
$title.css('color', finishColor);
|
||||
$title.children('.label-finish').show();
|
||||
if(item.color == '#2a5f29')
|
||||
{
|
||||
$item.children('.label-finish').css({'background-color':'#FFFFFF','color':'#2a5f29'});
|
||||
}
|
||||
else
|
||||
{
|
||||
$item.children('.label-finish').css({'background-color':'','color':'#FFFFFF'});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$title.css('color', '');
|
||||
$title.children('.label-finish').hide();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -445,14 +442,19 @@ function renderExecutionItem(item, $item)
|
||||
|
||||
/* Print execution name. */
|
||||
var $title = $titleBox.children('.title');
|
||||
var name = item.title ? item.title : item.name;
|
||||
if(!$title.length)
|
||||
{
|
||||
var icon = mode == 'new' ? 'run' : 'project';
|
||||
var viewMethod = item.execType == 'kanban' ? 'kanban' : 'view';
|
||||
if(privs.includes('viewExecution') && item.deleted == '0') $title = $('<a class="title"><i class="icon icon-' + icon + '"></i>' + item.name + '</a>').appendTo($titleBox).attr('href', createLink('execution', viewMethod, 'executionID=' + item.fromID));
|
||||
if(!privs.includes('viewExecution') || item.deleted == '1') $title = $('<div class="title"><i class="icon icon-' + icon + '"></i>' + item.name + '</div>').appendTo($titleBox);
|
||||
if(privs.includes('viewExecution') && item.deleted == '0') $title = $('<a class="title"><i class="icon icon-' + icon + '"></i>' + name + '</a>').appendTo($titleBox).attr('href', createLink('execution', viewMethod, 'executionID=' + item.fromID));
|
||||
if(!privs.includes('viewExecution') || item.deleted == '1') $title = $('<div class="title"><i class="icon icon-' + icon + '"></i>' + name + '</div>').appendTo($titleBox);
|
||||
}
|
||||
$title.attr('title', item.name);
|
||||
if(!$title.children('i').length)
|
||||
{
|
||||
$title.append('<i class="icon icon-run"></i>' + item.title);
|
||||
}
|
||||
$title.attr('title', name);
|
||||
|
||||
if(item.delay)
|
||||
{
|
||||
@@ -477,7 +479,7 @@ function renderExecutionItem(item, $item)
|
||||
{
|
||||
if(item.deleted == '0')
|
||||
{
|
||||
$statusBox = $('<span class="execStatus label label-' + item.status + '">' + executionLang.statusList[item.status] + '</span>').appendTo($info);
|
||||
$statusBox = $('<span class="execStatus label label-' + item.objectStatus + '">' + executionLang.statusList[item.objectStatus] + '</span>').appendTo($info);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -519,12 +521,17 @@ function renderReleaseItem(item, $item)
|
||||
|
||||
/* Print name. */
|
||||
var $title = $item.children('.releaseTitle');
|
||||
var name = item.title ? item.title : item.name;
|
||||
if(!$title.length)
|
||||
{
|
||||
if(privs.includes('viewRelease') && item.deleted == '0') $title = $('<a class="releaseTitle title"><i class="icon icon-publish"></i>' + item.name + '</a>').appendTo($item).attr('href', createLink('release', 'view', 'releaseID=' + item.fromID));
|
||||
if(!privs.includes('viewRelease') || item.deleted == '1') $title = $('<div class="releaseTitle"><i class="icon icon-publish"></i>' + item.name + '</div>').appendTo($item);
|
||||
if(privs.includes('viewRelease') && item.deleted == '0') $title = $('<a class="releaseTitle title"><i class="icon icon-publish"></i>' + name + '</a>').appendTo($item).attr('href', createLink('release', 'view', 'releaseID=' + item.fromID));
|
||||
if(!privs.includes('viewRelease') || item.deleted == '1') $title = $('<div class="releaseTitle"><i class="icon icon-publish"></i>' + name + '</div>').appendTo($item);
|
||||
}
|
||||
$title.attr('title', item.name);
|
||||
if(!$title.children('i').length)
|
||||
{
|
||||
$title.prepend('<i class="icon icon-publish"></i>');
|
||||
}
|
||||
$title.attr('title', name);
|
||||
|
||||
var $info = $item.children('.releaseInfo');
|
||||
if(!$info.length) $info = $(
|
||||
@@ -538,7 +545,7 @@ function renderReleaseItem(item, $item)
|
||||
{
|
||||
if(item.deleted == '0')
|
||||
{
|
||||
$statusBox = $('<span class="releaseStatus label label-' + item.status + '">' + releaseLang.statusList[item.status] + '</span>').appendTo($info);
|
||||
$statusBox = $('<span class="releaseStatus label label-' + item.objectStatus + '">' + releaseLang.statusList[item.objectStatus] + '</span>').appendTo($info);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -578,10 +585,15 @@ function renderProductplanItem(item, $item)
|
||||
|
||||
/* Print name. */
|
||||
var $title = $item.children('.productplanTitle');
|
||||
var name = item.title ? item.title : item.name;
|
||||
if(!$title.length)
|
||||
{
|
||||
if(privs.includes('viewPlan') && item.deleted == '0') $title = $('<a class="productplanTitle title"><i class="icon icon-delay"></i>' + item.title + '</a>').appendTo($item).attr('href', createLink('productplan', 'view', 'productplanID=' + item.fromID));
|
||||
if(!privs.includes('viewPlan') || item.deleted == '1') $title = $('<div class="productplanTitle"><i class="icon icon-delay"></i>' + item.title + '</div>').appendTo($item);
|
||||
if(privs.includes('viewPlan') && item.deleted == '0') $title = $('<a class="productplanTitle title"><i class="icon icon-delay"></i>' + name + '</a>').appendTo($item).attr('href', createLink('productplan', 'view', 'productplanID=' + item.fromID));
|
||||
if(!privs.includes('viewPlan') || item.deleted == '1') $title = $('<div class="productplanTitle"><i class="icon icon-delay"></i>' + name + '</div>').appendTo($item);
|
||||
}
|
||||
if(!$title.children('i').length)
|
||||
{
|
||||
$title.append('<i class="icon icon-delay"></i>' + name);
|
||||
}
|
||||
$title.attr('title', item.title);
|
||||
|
||||
@@ -597,7 +609,7 @@ function renderProductplanItem(item, $item)
|
||||
{
|
||||
if(item.deleted == '0')
|
||||
{
|
||||
$statusBox = $('<span class="productplanStatus label label-' + item.status + '">' + productplanLang.statusList[item.status] + '</span>').appendTo($info);
|
||||
$statusBox = $('<span class="productplanStatus label label-' + item.objectStatus + '">' + productplanLang.statusList[item.objectStatus] + '</span>').appendTo($info);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -646,12 +658,17 @@ function renderBuildItem(item, $item)
|
||||
|
||||
/* Print name. */
|
||||
var $title = $item.children('.buildTitle');
|
||||
var name = item.title ? item.title : item.name;
|
||||
if(!$title.length)
|
||||
{
|
||||
if(privs.includes('viewBuild') && item.deleted == '0') $title = $('<a class="buildTitle" data-app="project"><i class="icon icon-ver"></i>' + item.name + '</a>').appendTo($item).attr('href', createLink('build', 'view', 'buildID=' + item.fromID));
|
||||
if(!privs.includes('viewBuild') || item.deleted == '1') $title = $('<div class="buildTitle"><i class="icon icon-ver"></i>' + item.name + '</div>').appendTo($item);
|
||||
if(privs.includes('viewBuild') && item.deleted == '0') $title = $('<a class="buildTitle title" data-app="project"><i class="icon icon-ver"></i>' + name + '</a>').appendTo($item).attr('href', createLink('build', 'view', 'buildID=' + item.fromID));
|
||||
if(!privs.includes('viewBuild') || item.deleted == '1') $title = $('<div class="buildTitle title"><i class="icon icon-ver"></i>' + name + '</div>').appendTo($item);
|
||||
}
|
||||
$title.attr('title', item.name);
|
||||
if(!$title.children('i').length)
|
||||
{
|
||||
$title.append('<i class="icon icon-ver"></i>' + item.title);
|
||||
}
|
||||
$title.attr('title', name);
|
||||
|
||||
var $info = $item.children('.info');
|
||||
if(!$info.length) $info = $(
|
||||
@@ -1069,7 +1086,7 @@ function createCardMenu(options)
|
||||
if(!privs.length) return [];
|
||||
|
||||
var items = [];
|
||||
if(privs.includes('editCard')) items.push({label: kanbanLang.editCard, icon: 'edit', url: createLink('kanban', 'editCard', 'cardID=' + card.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}});
|
||||
if(privs.includes('editCard') && card.fromType == '') items.push({label: kanbanLang.editCard, icon: 'edit', url: createLink('kanban', 'editCard', 'cardID=' + card.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}});
|
||||
if(privs.includes('performable') && kanban.performable == 1)
|
||||
{
|
||||
if(card.status == 'done')
|
||||
@@ -1081,9 +1098,6 @@ function createCardMenu(options)
|
||||
items.push({label: kanbanLang.finishCard, icon: 'checked', onClick: function(){finishCard(card.id, card.kanban, card.region);}});
|
||||
}
|
||||
}
|
||||
if(privs.includes('archiveCard') && kanban.archived == '1') items.push({label: kanbanLang.archiveCard, icon: 'card-archive', url: createLink('kanban', 'archiveCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}});
|
||||
if(privs.includes('copyCard')) items.push({label: kanbanLang.copyCard, icon: 'copy', url: createLink('kanban', 'copyCard', 'cardID=' + card.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}});
|
||||
if(privs.includes('deleteCard')) items.push({label: kanbanLang.deleteCard, icon: 'trash', url: createLink('kanban', 'deleteCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}});
|
||||
if(privs.includes('moveCard'))
|
||||
{
|
||||
var moveCardItems = [];
|
||||
@@ -1107,10 +1121,11 @@ function createCardMenu(options)
|
||||
moveCardItems = moveCardItems.reverse();
|
||||
items.push({label: kanbanLang.moveCard, icon: 'move', items: moveCardItems});
|
||||
}
|
||||
if(privs.includes('archiveCard') && kanban.archived == '1') items.push({label: kanbanLang.archiveCard, icon: 'card-archive', url: createLink('kanban', 'archiveCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}});
|
||||
if(privs.includes('setCardColor'))
|
||||
{
|
||||
var cardColoritems = [];
|
||||
if(!card.color) color = "#fff";
|
||||
if(!card.color) card.color = "#fff";
|
||||
for(let i = 0 ; i < colorList.length ; i ++ )
|
||||
{
|
||||
var attr = card.color == colorList[i] ? '<i class="icon icon-check" style="margin-left: 5px"></i>' : '';
|
||||
@@ -1120,6 +1135,7 @@ function createCardMenu(options)
|
||||
};
|
||||
items.push({label: kanbanLang.cardColor, icon: 'color', items: cardColoritems});
|
||||
}
|
||||
if(privs.includes('deleteCard')) items.push({label: card.fromType == '' ? kanbanLang.deleteCard : kanbanLang.removeCard, icon: card.fromType == '' ? 'trash' : 'unlink', url: createLink('kanban', 'deleteCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}});
|
||||
|
||||
var bounds = options.$trigger[0].getBoundingClientRect();
|
||||
items.$options = {x: bounds.right, y: bounds.top};
|
||||
|
||||
@@ -40,6 +40,7 @@ $lang->kanban->moveCard = 'Move Card';
|
||||
$lang->kanban->cardColor = 'Card Color';
|
||||
$lang->kanban->setCardColor = 'Set Card Color';
|
||||
$lang->kanban->deleteCard = 'Delete Card';
|
||||
$lang->kanban->removeCard = 'Remove Card';
|
||||
$lang->kanban->assigntoCard = 'Assign';
|
||||
$lang->kanban->setting = 'Setting';
|
||||
$lang->kanban->enableArchived = 'Enable Archived';
|
||||
@@ -365,6 +366,7 @@ $lang->kanbancard->confirmArchive = 'Are you sure to archive this card? After
|
||||
$lang->kanbancard->confirmDelete = 'Are you sure to delete this card? After deleting the card, it will be deleted from the Kanban. You can only view it in the system recycle bin.';
|
||||
$lang->kanbancard->confirmRestore = "Are you sure you want to restore this card? After the card is restored, the card will be restored to the '%s' Kanban column.";
|
||||
$lang->kanbancard->confirmRestoreTip = "The card's column has been archived or deleted, please restore '%s' column first.";
|
||||
$lang->kanbancard->confirmRemove = 'Are you sure to remove this card? After removing the card, the original data would not be affected.The card would be removed from the Kanban and counld not be restored.';
|
||||
|
||||
$lang->kanbancard->priList[1] = 1;
|
||||
$lang->kanbancard->priList[2] = 2;
|
||||
|
||||
@@ -40,6 +40,7 @@ $lang->kanban->moveCard = '移动卡片';
|
||||
$lang->kanban->cardColor = '卡片颜色';
|
||||
$lang->kanban->setCardColor = '设置卡片颜色';
|
||||
$lang->kanban->deleteCard = '删除卡片';
|
||||
$lang->kanban->removeCard = '移除卡片';
|
||||
$lang->kanban->assigntoCard = '指派';
|
||||
$lang->kanban->setting = '设置';
|
||||
$lang->kanban->enableArchived = '设置归档功能';
|
||||
@@ -365,6 +366,7 @@ $lang->kanbancard->confirmArchive = '您确认归档该卡片吗?归档卡
|
||||
$lang->kanbancard->confirmDelete = '您确认删除该卡片吗?删除卡片后,该卡片将从看板中删除,您只能通过系统回收站查看。';
|
||||
$lang->kanbancard->confirmRestore = '您确定要还原该卡片吗?还原卡片后,该卡片将还原到“%s”看板列中。';
|
||||
$lang->kanbancard->confirmRestoreTip = '该卡片所属的看板列已被归档或删除,请先还原“%s”看板列。';
|
||||
$lang->kanbancard->confirmRemove = '您确认移除该卡片吗?移除卡片后,源数据不会受到影响,卡片将从看板中移除且无法恢复。';
|
||||
|
||||
$lang->kanbancard->priList[1] = 1;
|
||||
$lang->kanbancard->priList[2] = 2;
|
||||
|
||||
@@ -1113,16 +1113,17 @@ class kanbanModel extends model
|
||||
* @param int $kanbanID
|
||||
* @param object $cards
|
||||
* @param string $fromType
|
||||
* @param int $archived
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getImportedCards($kanbanID, $cards, $fromType)
|
||||
public function getImportedCards($kanbanID, $cards, $fromType, $archived = 0)
|
||||
{
|
||||
/* Get imported cards based on imported object type. */
|
||||
$objectCards = $this->dao->select('*')->from(TABLE_KANBANCARD)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere('kanban')->eq($kanbanID)
|
||||
->andWhere('archived')->eq(0)
|
||||
->andWhere('archived')->eq($archived)
|
||||
->andWhere('fromType')->eq($fromType)
|
||||
->fetchGroup('fromID', 'id');
|
||||
|
||||
@@ -1168,6 +1169,8 @@ class kanbanModel extends model
|
||||
$objectCard->execType = $object->type;
|
||||
}
|
||||
|
||||
$objectCard->objectStatus = $objectCard->status;
|
||||
$objectCard->status = $objectCard->progress == 100 ? 'done' : 'doing';
|
||||
$cards[$cardID] = $objectCard;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#archivedCards .info > .users > span:after {right: -4px; content: ''; display: block; position: absolute; width: 2px; height: 2px; background-color: #8990a2; top: 0px; border-radius: 50%;}
|
||||
#archivedCards .info > .users .avatar {display: inline-block; position: relative; border-radius: 50%; top: -5px; margin: 5px; right: -7px; margin-left: -4px;}
|
||||
#archivedCards .cardName {word-wrap: break-word;}
|
||||
#archivedCards .card-item .icon {margin-right:2px;}
|
||||
#archivedCards .card-item .red {background-color: #b10b0b;}
|
||||
#archivedCards .card-item .yellow {background-color: #cfa227;}
|
||||
#archivedCards .card-item .green {background-color: #2a5f29;}
|
||||
@@ -44,6 +45,12 @@
|
||||
#archivedCards .progress-box {width: 97%;}
|
||||
#performable {padding: 25px 10px !important;}
|
||||
</style>
|
||||
<?php
|
||||
$app->loadLang('execution');
|
||||
$app->loadLang('release');
|
||||
$app->loadLang('build');
|
||||
$app->loadLang('productplan');
|
||||
?>
|
||||
<div class='panel'>
|
||||
<div class='panel-heading text-center'>
|
||||
<strong><?php echo $lang->kanban->archivedCard;?></strong>
|
||||
@@ -76,10 +83,21 @@
|
||||
<?php if($card->status == 'done'):?>
|
||||
<div class="label" style="<?php echo $labelColor;?>"><?php echo $lang->kanban->finished;?></div>
|
||||
<?php endif;?>
|
||||
<?php if(empty($card->fromType)):?>
|
||||
<?php echo html::a($this->createLink('kanban', 'viewCard', "cardID=$card->id", '', true), $card->name, '', "class='cardName iframe' data-toggle='modal' data-width='80%' title='$card->name'");?>
|
||||
<div class="info">
|
||||
<span class="pri label-pri label-pri-<?php echo $card->pri;?>"><?php echo $card->pri;?></span>
|
||||
<?php if($card->estimate and $card->estimate != 0) echo "<span class='text-gray'>{$card->estimate}h</span>";?>
|
||||
<?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 "<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>"
|
||||
?>
|
||||
<?php endif;?>
|
||||
<?php if(helper::isZeroDate($card->end) and !helper::isZeroDate($card->begin)):?>
|
||||
<span class="time label label-light"><?php echo date("m/d", strtotime($card->begin)) . $lang->kanbancard->beginAB;?></span>
|
||||
<?php endif;?>
|
||||
@@ -137,7 +155,7 @@
|
||||
|
||||
if($canRestore) echo html::a(inlink('restoreCard', "cardID={$card->id}"), $lang->kanban->restore, '', "class='btn btn-xs btn-primary' target='hiddenwin'");
|
||||
|
||||
if($canDelete) echo html::a($this->createLink('kanban', 'deleteCard', "cardID=$card->id"), $lang->delete, '', "class='btn btn-xs delete-card' target='hiddenwin'");
|
||||
if($canDelete) echo html::a($this->createLink('kanban', 'deleteCard', "cardID=$card->id"), $card->fromType == '' ? $lang->delete : $lang->unlink, '', "class='btn btn-xs delete-card' target='hiddenwin'");
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -152,5 +170,17 @@ $(function()
|
||||
{
|
||||
$('#archivedCards').animate({right: -400}, 500);
|
||||
});
|
||||
$('.card-item').each(function()
|
||||
{
|
||||
var $item = $(this).children('.col-xs-10').children('.kanban-item');
|
||||
var icon = '';
|
||||
|
||||
if($item.children('.build').length) icon = '<i class="icon icon-ver">';
|
||||
if($item.children('.execution').length) icon = '<i class="icon icon-run">';
|
||||
if($item.children('.productplan').length) icon = '<i class="icon icon-delay">';
|
||||
if($item.children('.release').length) icon = '<i class="icon icon-publish">';
|
||||
|
||||
$item.children('.cardName').prepend(icon);
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -1197,12 +1197,14 @@ class product extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function all($browseType = 'noclosed', $orderBy = 'order_asc')
|
||||
public function all($browseType = 'noclosed', $orderBy = 'order_asc', $param = 0)
|
||||
{
|
||||
/* 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);
|
||||
@@ -1210,9 +1212,12 @@ class product extends control
|
||||
}
|
||||
|
||||
/* Process product structure. */
|
||||
$productStats = $this->product->getStats($orderBy, '', $browseType, '', 'story');
|
||||
$productStats = $this->product->getStats($orderBy, '', $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;
|
||||
|
||||
|
||||
+100
-2
@@ -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.
|
||||
*
|
||||
@@ -1047,6 +1089,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.
|
||||
*
|
||||
@@ -1567,13 +1634,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);
|
||||
@@ -2022,6 +2089,37 @@ class productModel extends model
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build operate menu.
|
||||
*
|
||||
* @param object $product
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildOperateMenu($product, $type = 'view')
|
||||
{
|
||||
$menu = '';
|
||||
$params = "product=$product->id";
|
||||
|
||||
if($type == 'view')
|
||||
{
|
||||
$menu .= "<div class='divider'></div>";
|
||||
$menu .= $this->buildFlowMenu('product', $product, $type, 'direct');
|
||||
$menu .= "<div class='divider'></div>";
|
||||
|
||||
$menu .= $this->buildMenu('product', 'close', $params, $product, $type, '', '', '', '', "data-app='product'");
|
||||
$menu .= "<div class='divider'></div>";
|
||||
}
|
||||
|
||||
$menu .= $this->buildMenu('product', 'edit', $params, $product, $type);
|
||||
|
||||
if($type == 'view') $menu .= $this->buildMenu('product', 'delete', $params, $product, $type, 'trash', 'hiddenwin');
|
||||
if($type == 'browse' && common::hasPriv('product', 'updateOrder')) $menu .= "<i class='icon icon-move text-blue'></i>";
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the link from module,method,extra,branch.
|
||||
*
|
||||
|
||||
@@ -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)?>
|
||||
@@ -31,11 +32,9 @@
|
||||
</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
|
||||
$canOrder = common::hasPriv('product', 'updateOrder');
|
||||
$canBatchEdit = common::hasPriv('product', 'batchEdit');
|
||||
?>
|
||||
<?php $canBatchEdit = common::hasPriv('product', 'batchEdit'); ?>
|
||||
<table id="productList" class="table has-sort-head table-nested table-fixed">
|
||||
<?php $vars = "browseType=$browseType&orderBy=%s";?>
|
||||
<thead>
|
||||
@@ -215,12 +214,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 common::printIcon('product', 'edit', "product=$product->id", $product, 'list', 'edit');?>
|
||||
<?php if($canOrder):?>
|
||||
<i class="icon icon-move text-blue"></i>
|
||||
<?php endif;?>
|
||||
</td>
|
||||
<td class='c-actions sort-handler'><?php echo $this->buildOperateMenu($product, 'browse');?></td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
|
||||
@@ -158,24 +158,10 @@
|
||||
<div class='main-actions'>
|
||||
<div class="btn-toolbar">
|
||||
<?php
|
||||
$params = "product=$product->id";
|
||||
$browseLink = $this->session->productList ? $this->session->productList : inlink('browse', "productID=$product->id");
|
||||
common::printBack($browseLink);
|
||||
if(!$product->deleted)
|
||||
{
|
||||
echo $this->buildOperateMenu($product, 'view');
|
||||
|
||||
echo "<div class='divider'></div>";
|
||||
|
||||
if($product->status != 'closed')
|
||||
{
|
||||
common::printIcon('product', 'close', $params, $product, 'button', '', '', 'iframe', true);
|
||||
echo "<div class='divider'></div>";
|
||||
}
|
||||
|
||||
common::printIcon('product', 'edit', $params, $product);
|
||||
common::printIcon('product', 'delete', $params, $product, 'button', 'trash', 'hiddenwin');
|
||||
}
|
||||
if(!$product->deleted) echo $this->buildOperateMenu($product, 'view');
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1002,17 +1002,21 @@ class productplanModel extends model
|
||||
*
|
||||
* @param object $plan
|
||||
* @param string $action
|
||||
* @param string $module
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function isClickable($plan, $action)
|
||||
public static function isClickable($plan, $action, $module = 'productplan')
|
||||
{
|
||||
$action = strtolower($action);
|
||||
$clickable = commonModel::hasPriv('productplan', $action);
|
||||
$clickable = commonModel::hasPriv($module, $action);
|
||||
if(!$clickable) return false;
|
||||
|
||||
switch($action)
|
||||
{
|
||||
case 'create' :
|
||||
if($plan->parent > 0 or strpos('done,closed', $plan->status) !== false) return false;
|
||||
break;
|
||||
case 'start' :
|
||||
if($plan->status != 'wait' or $plan->parent < 0) return false;
|
||||
break;
|
||||
@@ -1025,8 +1029,100 @@ class productplanModel extends model
|
||||
case 'activate' :
|
||||
if($plan->status == 'wait' or $plan->status == 'doing' or $plan->parent < 0) return false;
|
||||
break;
|
||||
case 'delete' :
|
||||
if($plan->parent < 0) return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if($module == 'execution' && $action == 'create')
|
||||
{
|
||||
if($plan->parent < 0 || $plan->expired || in_array($plan->status, array('done', 'closed'))) return false;
|
||||
|
||||
$product = $this->loadModel('product')->getById($plan->product);
|
||||
$branchList = $this->loadModel('branch')->getList($plan->product, 0, 'all');
|
||||
|
||||
$branchStatusList = array();
|
||||
foreach($branchList as $productBranch) $branchStatusList[$productBranch->id] = $productBranch->status;
|
||||
|
||||
if($product->type != 'normal')
|
||||
{
|
||||
$branchStatus = isset($branchStatusList[$plan->branch]) ? $branchStatusList[$plan->branch] : '';
|
||||
if($branchStatus == 'closed') return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build operate menu.
|
||||
*
|
||||
* @param object $plan
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildOperateMenu($plan, $type = 'view')
|
||||
{
|
||||
$params = "planID=$plan->id";
|
||||
|
||||
$menu = '';
|
||||
$menu .= $this->buildMenu('productplan', 'start', $params, $plan, $type, 'play', 'hiddenwin', '', false, '', $this->lang->productplan->startAB);
|
||||
$menu .= $this->buildMenu('productplan', 'finish', $params, $plan, $type, 'checked', 'hiddenwin', '', false, '', $this->lang->productplan->finishAB);
|
||||
$menu .= $this->buildMenu('productplan', 'close', $params, $plan, $type, 'off', 'hiddenwin', 'iframe', true, '', $this->lang->productplan->closeAB);
|
||||
|
||||
if($type == 'view') $menu .= $this->buildMenu('productplan', 'activate', $params, $plan, $type, 'magic', 'hiddenwin', '', false, '', $this->lang->productplan->activateAB);
|
||||
|
||||
if($type == 'browse')
|
||||
{
|
||||
if($this->isClickable($plan, 'create', 'execution'))
|
||||
{
|
||||
$executionLink = $this->config->systemMode == 'new' ? '#projects' : helper::createLink('execution', 'create', "projectID=0&executionID=0©ExecutionID=0&plan=$plan->id&confirm=no&productID=$plan->product");
|
||||
if($this->config->systemMode == 'new')
|
||||
{
|
||||
$menu .= html::a($executionLink, '<i class="icon-plus"></i>', '', "data-toggle='modal' data-id='$plan->id' onclick='getPlanID(this, $plan->branch)' class='btn' title='{$this->lang->productplan->createExecution}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
$menu .= html::a($executionLink, '<i class="icon-plus"></i>', '', "class='btn' title='{$this->lang->productplan->createExecution}'");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$menu .= "<button type='button' class='btn disabled'><i class='icon-plus' title='{$this->lang->productplan->createExecution}'></i></button>";
|
||||
}
|
||||
|
||||
if(common::hasPriv('productplan', 'linkStory', $plan) and $plan->parent >= 0)
|
||||
{
|
||||
$menu .= $this->buildMenu('productplan', 'view', "{$params}&type=story&orderBy=id_desc&link=true", $plan, $type, 'link', '', '', '', '', $this->lang->productplan->linkStory);
|
||||
}
|
||||
else
|
||||
{
|
||||
$menu .= "<button type='button' class='disabled btn'><i class='icon-link' title='{$this->lang->productplan->linkStory}'></i></button>";
|
||||
}
|
||||
|
||||
if(common::hasPriv('productplan', 'linkBug', $plan) and $plan->parent >= 0)
|
||||
{
|
||||
$menu .= $this->buildMenu('productplan', 'view', "{$params}&type=bug&orderBy=id_desc&link=true", $plan, $type, 'bug', '', '', '', '', $this->lang->productplan->linkBug);
|
||||
}
|
||||
else
|
||||
{
|
||||
$menu .= "<button type='button' class='disabled btn'><i class='icon-bug' title='{$this->lang->productplan->linkBug}'></i></button>";
|
||||
}
|
||||
|
||||
$menu .= $this->buildMenu('productplan', 'edit', $params, $plan, $type);
|
||||
}
|
||||
|
||||
$menu .= $this->buildMenu('productplan', 'create', "product={$plan->product}&branch={$plan->branch}&parent={$plan->id}", $plan, $type, 'split', '', '', '', '', $this->lang->productplan->children);
|
||||
|
||||
if($type == 'browse') $menu .= $this->buildMenu('productplan', 'delete', "{$params}&confirm=no", $plan, $type, 'trash', 'hiddenwin', '', '', $this->lang->productplan->delete);
|
||||
|
||||
if($type == 'view')
|
||||
{
|
||||
if(common::hasPriv('productplan', 'edit', $plan)) $menu .= html::a(helper::createLink('productplan', 'edit', $params), "<i class='icon-common-edit icon-edit'></i> " . $this->lang->edit, '', "class='btn btn-link' title='{$this->lang->edit}'");
|
||||
if($plan->parent >= 0 && common::hasPriv('productplan', 'delete', $plan)) $menu .= html::a(helper::createLink('productplan', 'delete', $params), "<i class='icon-common-delete icon-trash'></i> " . $this->lang->delete, '', "class='btn btn-link' title='{$this->lang->delete}' target='hiddenwin'");
|
||||
}
|
||||
|
||||
return $menu;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,67 +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
|
||||
if($plan->parent >= 0 )
|
||||
{
|
||||
$attr = "target='hiddenwin'";
|
||||
common::printIcon('productplan', 'start', "planID=$plan->id", $plan, 'list', 'play', '', '', false, $attr);
|
||||
common::printIcon('productplan', 'finish', "planID=$plan->id", $plan, 'list', 'checked', '', '', false, $attr);
|
||||
common::printIcon('productplan', 'close', "planID=$plan->id", $plan, 'list', 'off', '', 'iframe', true);
|
||||
}
|
||||
|
||||
$attr = $plan->expired ? "disabled='disabled'" : '';
|
||||
$class = '';
|
||||
if($product->type != 'normal')
|
||||
{
|
||||
$branchStatus = isset($branchStatusList[$plan->branch]) ? $branchStatusList[$plan->branch] : '';
|
||||
if($branchStatus == 'closed') $class = 'disabled';
|
||||
}
|
||||
if(common::hasPriv('execution', 'create', $plan) and $plan->parent >= 0)
|
||||
{
|
||||
$disabled = '';
|
||||
$executionLink = $config->systemMode == 'new' ? '#projects' : $this->createLink('execution', 'create', "projectID=0&executionID=0©ExecutionID=0&plan=$plan->id&confirm=no&productID=$productID");
|
||||
|
||||
if(in_array($plan->status, array('done', 'closed'))) $disabled = 'disabled';
|
||||
|
||||
if($config->systemMode == 'new')
|
||||
{
|
||||
echo html::a($executionLink, '<i class="icon-plus"></i>', '', "data-toggle='modal' data-id='$plan->id' onclick='getPlanID(this, $plan->branch)' class='btn {$disabled} {$class}' title='{$lang->productplan->createExecution}' $attr");
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::a($executionLink, '<i class="icon-plus"></i>', '', "class='btn {$disabled}' title='{$lang->productplan->createExecution}' $attr");
|
||||
}
|
||||
}
|
||||
if(common::hasPriv('productplan', 'linkStory', $plan) and $plan->parent >= 0) echo html::a(inlink('view', "planID=$plan->id&type=story&orderBy=id_desc&link=true"), '<i class="icon-link"></i>', '', "class='btn' title='{$lang->productplan->linkStory}'");
|
||||
if(common::hasPriv('productplan', 'linkBug', $plan) and $plan->parent >= 0) echo html::a(inlink('view', "planID=$plan->id&type=bug&orderBy=id_desc&link=true"), '<i class="icon-bug"></i>', '', "class='btn' title='{$lang->productplan->linkBug}'");
|
||||
common::printIcon('productplan', 'edit', "planID=$plan->id", $plan, 'list');
|
||||
if(common::hasPriv('productplan', 'create', $plan))
|
||||
{
|
||||
if($plan->parent > 0 or strpos('done,closed', $plan->status) !== false)
|
||||
{
|
||||
echo "<button type='button' class='disabled btn'><i class='disabled icon-split' title='{$this->lang->productplan->children}'></i></button> ";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::a($this->createLink('productplan', 'create', "product=$productID&branch=$branch&parent={$plan->id}"), "<i class='icon-split'></i>", '', "class='btn {$class}' title='{$this->lang->productplan->children}'");
|
||||
}
|
||||
}
|
||||
|
||||
if(common::hasPriv('productplan', 'delete', $plan))
|
||||
{
|
||||
$deleteURL = '###';
|
||||
$disabled = 'disabled';
|
||||
if($plan->parent >= 0)
|
||||
{
|
||||
$deleteURL = $this->createLink('productplan', 'delete', "planID=$plan->id&confirm=no");
|
||||
$disabled = '';
|
||||
}
|
||||
echo html::a($deleteURL, '<i class="icon-trash"></i>', 'hiddenwin', "class='btn {$disabled}' title='{$lang->productplan->delete}'");
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td class='c-actions'><?php echo $this->buildOperateMenu($plan, 'browse'); ?></td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
|
||||
@@ -38,31 +38,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class='btn-toolbar pull-right' id='actionsBox'>
|
||||
<?php
|
||||
if(!$plan->deleted && !isonlybody())
|
||||
{
|
||||
echo $this->buildOperateMenu($plan, 'view');
|
||||
|
||||
if($plan->parent >= 0)
|
||||
{
|
||||
$attr = "target='hiddenwin'";
|
||||
$class = $plan->status == 'wait' ? '' : 'disabled';
|
||||
|
||||
common::printLink('productplan', 'start', "planID=$plan->id", "<i class='icon-play'></i>{$lang->productplan->startAB}", '', "class='btn btn-link {$class}'{$attr} title='{$lang->productplan->start}'", '', false, $plan);
|
||||
$class = $plan->status == 'doing' ? '' : 'disabled';
|
||||
common::printLink('productplan', 'finish', "planID=$plan->id", "<i class='icon-checked'></i>{$lang->productplan->finishAB}", '', "class='btn btn-link {$class}' target='hiddenwin' title='{$lang->productplan->finish}'", '', false, $plan);
|
||||
$class = $plan->status !== 'closed' ? 'iframe' : 'disabled';
|
||||
common::printLink('productplan', 'close', "planID=$plan->id", "<i class='icon-off'></i>{$lang->productplan->closeAB}", '', "class='btn btn-link {$class}' title='{$lang->productplan->close}'", '', true, $plan);
|
||||
$class = in_array($plan->status, array('closed', 'done')) ? '' : 'disabled';
|
||||
common::printLink('productplan', 'activate', "planID=$plan->id", "<i class='icon-magic'></i>{$lang->productplan->activateAB}", '', "class='btn btn-link {$class}' target='hiddenwin' title='{$lang->productplan->activate}'", '', false, $plan);
|
||||
}
|
||||
|
||||
$class = (isset($branchStatus) and $branchStatus == 'closed') ? 'disabled' : '';
|
||||
if(common::hasPriv('productplan', 'create', $plan) and $plan->parent <= 0 and strpos('wait,doing', $plan->status) !== false) echo html::a($this->createLink('productplan', 'create', "product={$plan->product}&branch={$plan->branch}&parent={$plan->id}"), "<i class='icon-split'></i> " . $this->lang->productplan->children , '', "class='btn btn-link {$class}' title='{$this->lang->productplan->children}'");
|
||||
if(common::hasPriv('productplan', 'edit', $plan)) echo html::a($this->createLink('productplan', 'edit', "planID=$plan->id"), "<i class='icon-common-edit icon-edit'></i> " . $this->lang->edit, '', "class='btn btn-link' title='{$this->lang->edit}'");
|
||||
if(common::hasPriv('productplan', 'delete', $plan) and $plan->parent >= 0) echo html::a($this->createLink('productplan', 'delete', "planID=$plan->id"), "<i class='icon-common-delete icon-trash'></i> " . $this->lang->delete, '', "class='btn btn-link' title='{$this->lang->delete}' target='hiddenwin'");
|
||||
}
|
||||
?>
|
||||
<?php if(!$plan->deleted && !isonlybody()) echo $this->buildOperateMenu($plan, 'view'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div id='mainContent' class='main-content'>
|
||||
|
||||
@@ -41,15 +41,18 @@ class release extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function browse($productID, $branch = 'all', $type = 'all', $orderBy = 't1.date_desc')
|
||||
public function browse($productID, $branch = 'all', $type = 'all', $orderBy = 't1.date_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
$this->commonAction($productID, $branch);
|
||||
$this->session->set('releaseList', $this->app->getURI(true), 'product');
|
||||
|
||||
$this->view->title = $this->view->product->name . $this->lang->colon . $this->lang->release->browse;
|
||||
$this->view->position[] = $this->lang->release->browse;
|
||||
$this->view->releases = $this->release->getList($productID, $branch, $type, $orderBy);
|
||||
$this->view->releases = $this->release->getList($productID, $branch, $type, $orderBy, $pager);
|
||||
$this->view->type = $type;
|
||||
$this->view->pager = $pager;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
|
||||
@@ -121,9 +121,6 @@ class releaseModel extends model
|
||||
/* Check build if build is required. */
|
||||
if(strpos($this->config->release->create->requiredFields, 'build') !== false and $this->post->build == false) return dao::$errors[] = sprintf($this->lang->error->notempty, $this->lang->release->build);
|
||||
|
||||
/* Check date must be not more than today. */
|
||||
if($this->post->date > date('Y-m-d')) return dao::$errors[] = $this->lang->release->errorDate;
|
||||
|
||||
$release = fixer::input('post')
|
||||
->add('product', (int)$productID)
|
||||
->add('branch', (int)$branch)
|
||||
|
||||
@@ -105,5 +105,8 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif;?>
|
||||
<div class='table-footer'>
|
||||
<?php $pager->show('right', 'pagerjs');?>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -75,10 +75,4 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function()
|
||||
{
|
||||
$(".form-date").datetimepicker('setEndDate', '<?php echo date(DT_DATE1)?>');
|
||||
});
|
||||
</script>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -1351,7 +1351,7 @@ class story extends control
|
||||
if(isonlybody())
|
||||
{
|
||||
$execution = $this->execution->getByID($this->session->execution);
|
||||
if($this->app->tab == 'execution' and $execution->type == 'kanban' and $this->app->tab == 'execution')
|
||||
if($this->app->tab == 'execution' and $execution->type == 'kanban')
|
||||
{
|
||||
$this->loadModel('kanban')->updateLane($this->session->execution, 'story', $storyID);
|
||||
$kanbanData = $this->kanban->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
|
||||
|
||||
@@ -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();
|
||||
@@ -3038,6 +3039,8 @@ class storyModel extends model
|
||||
public function closeParentRequirement($storyID)
|
||||
{
|
||||
$parentID = $this->dao->select('BID')->from(TABLE_RELATION)->where('AID')->eq($storyID)->fetch();
|
||||
if(empty($parentID)) return;
|
||||
|
||||
$stories = $this->dao->select('t2.id, t2.status')->from(TABLE_RELATION)->alias('t1')
|
||||
->leftJoin(TABLE_STORY)->alias('t2')->on('t2.id=t1.AID')
|
||||
->where('t1.BType')->eq('requirement')
|
||||
|
||||
+114
-16
@@ -1713,22 +1713,8 @@ class testcaseModel extends model
|
||||
echo $case->stepNumber;
|
||||
break;
|
||||
case 'actions':
|
||||
if($canBeChanged)
|
||||
{
|
||||
if($case->needconfirm or $browseType == 'needconfirm')
|
||||
{
|
||||
common::printIcon('testcase', 'confirmstorychange', "caseID=$case->id", $case, 'list', 'confirm', 'hiddenwin', '', '', '', $this->lang->confirm);
|
||||
break;
|
||||
}
|
||||
|
||||
common::printIcon('testtask', 'results', "runID=0&caseID=$case->id", $case, 'list', '', '', 'iframe', true, "data-width='95%'");
|
||||
common::printIcon('testtask', 'runCase', "runID=0&caseID=$case->id&version=$case->version", $case, 'list', 'play', '', 'runCase iframe', false, "data-width='95%'");
|
||||
common::printIcon('testcase', 'edit', "caseID=$case->id", $case, 'list');
|
||||
if($this->config->testcase->needReview or !empty($this->config->testcase->forceReview)) common::printIcon('testcase', 'review', "caseID=$case->id", $case, 'list', 'glasses', '', 'iframe');
|
||||
common::printIcon('testcase', 'createBug', "product=$case->product&branch=$case->branch&extra=caseID=$case->id,version=$case->version,runID=", $case, 'list', 'bug', '', 'iframe', '', "data-width='90%'");
|
||||
common::printIcon('testcase', 'create', "productID=$case->product&branch=$case->branch&moduleID=$case->module&from=testcase¶m=$case->id", $case, 'list', 'copy');
|
||||
}
|
||||
|
||||
$case->browseType = $browseType;
|
||||
echo $this->buildOperateMenu($case, 'browse');
|
||||
break;
|
||||
}
|
||||
echo '</td>';
|
||||
@@ -2014,4 +2000,116 @@ class testcaseModel extends model
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build test case menu.
|
||||
*
|
||||
* @param object $case
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildOperateMenu($case, $type = 'view')
|
||||
{
|
||||
$function = 'buildOperate' . ucfirst($type) . 'Menu';
|
||||
return $this->$function($case);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build test case view menu.
|
||||
*
|
||||
* @param object $case
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildOperateViewMenu($case)
|
||||
{
|
||||
if($case->deleted) return '';
|
||||
|
||||
$menu = '';
|
||||
$params = "caseID=$case->id";
|
||||
$extraParams = "runID=$case->runID&$params";
|
||||
if(!$case->needconfirm)
|
||||
{
|
||||
if(!$case->isLibCase)
|
||||
{
|
||||
if($this->app->getViewType() == 'xhtml')
|
||||
{
|
||||
$menu .= $this->buildMenu('testtask', 'runCase', "$extraParams&version=$case->currentVersion", $case, 'view', 'play', '', 'showinonlybody', false, "data-width='95%'");
|
||||
$menu .= $this->buildMenu('testtask', 'results', "$extraParams&version=$case->version", $case, 'view', '', '', 'showinonlybody', false, "data-width='95%'");
|
||||
}
|
||||
else
|
||||
{
|
||||
$menu .= $this->buildMenu('testtask', 'runCase', "$extraParams&version=$case->currentVersion", $case, 'view', 'play', '', 'showinonlybody iframe', false, "data-width='95%'");
|
||||
$menu .= $this->buildMenu('testtask', 'results', "$extraParams&version=$case->version", $case, 'view', '', '', 'showinonlybody iframe', false, "data-width='95%'");
|
||||
}
|
||||
if($case->caseFails > 0)
|
||||
{
|
||||
$menu .= $this->buildMenu('testcase', 'createBug', "product=$case->product&branch=$case->branch&extra=$params,version=$case->version,runID=$case->runID", $case, 'view', 'bug', '', 'iframe', '', "data-width='90%'");
|
||||
}
|
||||
}
|
||||
if($this->config->testcase->needReview || !empty($this->config->testcase->forceReview))
|
||||
{
|
||||
$menu .= $this->buildMenu('testcase', 'review', $params, $case, 'view', '', '', 'iframe', '', '', $this->lang->testcase->reviewAB);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$menu .= $this->buildMenu('testcase', 'confirmstorychange', $params, $case, 'view', 'confirm', 'hiddenwin', '', '', '', $this->lang->confirm);
|
||||
}
|
||||
|
||||
$menu .= "<div class='divider'></div>";
|
||||
$menu .= $this->buildFlowMenu('testcase', $case, 'view', 'direct');
|
||||
$menu .= "<div class='divider'></div>";
|
||||
|
||||
if(!$case->needconfirm)
|
||||
{
|
||||
if(!isonlybody()) $menu .= $this->buildMenu('testcase', 'edit', $params, $case, 'view', '', '', 'showinonlybody');
|
||||
if(!$case->isLibCase && $case->auto != 'unit')
|
||||
{
|
||||
$menu .= $this->buildMenu('testcase', 'create', "productID=$case->product&branch=$case->branch&moduleID=$case->module&from=testcase¶m=$case->id", $case, 'view', 'copy');
|
||||
}
|
||||
if($case->isLibCase && common::hasPriv('caselib', 'createCase'))
|
||||
{
|
||||
echo html::a(helper::createLink('caselib', 'createCase', "libID=$case->lib&moduleID=$case->module¶m=$case->id"), "<i class='icon-copy'></i>", '', "class='btn' title='{$this->lang->testcase->copy}'");
|
||||
}
|
||||
|
||||
$menu .= $this->buildMenu('testcase', 'delete', $params, $case, 'view', 'trash', 'hiddenwin', '');
|
||||
}
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build test case browse menu.
|
||||
*
|
||||
* @param object $case
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildOperateBrowseMenu($case)
|
||||
{
|
||||
$canBeChanged = common::canBeChanged('case', $case);
|
||||
if(!$canBeChanged) return '';
|
||||
|
||||
$menu = '';
|
||||
$params = "caseID=$case->id";
|
||||
|
||||
if($case->needconfirm || $case->browseType == 'needconfirm')
|
||||
{
|
||||
return $this->buildMenu('testcase', 'confirmstorychange', $params, $case, 'browse', 'confirm', 'hiddenwin', '', '', '', $this->lang->confirm);
|
||||
}
|
||||
|
||||
$menu .= $this->buildMenu('testtask', 'results', "runID=0&$params", $case, 'browse', '', '', 'iframe', true, "data-width='95%'");
|
||||
$menu .= $this->buildMenu('testtask', 'runCase', "runID=0&$params&version=$case->version", $case, 'browse', 'play', '', 'runCase iframe', false, "data-width='95%'");
|
||||
$menu .= $this->buildMenu('testcase', 'edit', "caseID=$case->id", $case, 'browse');
|
||||
if($this->config->testcase->needReview || !empty($this->config->testcase->forceReview))
|
||||
{
|
||||
common::printIcon('testcase', 'review', $params, $case, 'browse', 'glasses', '', 'iframe');
|
||||
}
|
||||
$menu .= $this->buildMenu('testcase', 'createBug', "product=$case->product&branch=$case->branch&extra=caseID=$case->id,version=$case->version,runID=", $case, 'browse', 'bug', '', 'iframe', '', "data-width='90%'");
|
||||
$menu .= $this->buildMenu('testcase', 'create', "productID=$case->product&branch=$case->branch&moduleID=$case->module&from=testcase¶m=$case->id", $case, 'browse', 'copy');
|
||||
|
||||
return $menu;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,41 +112,11 @@
|
||||
<div class='main-actions'>
|
||||
<div class="btn-toolbar">
|
||||
<?php common::printBack($browseLink);?>
|
||||
<?php if(!$case->deleted):?>
|
||||
<?php if(!isonlybody()) echo "<div class='divider'></div>";?>
|
||||
<?php if(!$case->needconfirm):?>
|
||||
<?php
|
||||
if(!$isLibCase)
|
||||
{
|
||||
if(!isonlybody()) echo "<div class='divider'></div>";
|
||||
if($this->app->getViewType() == 'xhtml')
|
||||
{
|
||||
common::printIcon('testtask', 'runCase', "runID=$runID&caseID=$case->id&version=$case->currentVersion", $case, 'button', 'play', '', 'showinonlybody', false, "data-width='95%'");
|
||||
common::printIcon('testtask', 'results', "runID=$runID&caseID=$case->id&version=$case->version", $case, 'button', '', '', 'showinonlybody', false, "data-width='95%'");
|
||||
}
|
||||
else
|
||||
{
|
||||
common::printIcon('testtask', 'runCase', "runID=$runID&caseID=$case->id&version=$case->currentVersion", $case, 'button', 'play', '', 'showinonlybody iframe', false, "data-width='95%'");
|
||||
common::printIcon('testtask', 'results', "runID=$runID&caseID=$case->id&version=$case->version", $case, 'button', '', '', 'showinonlybody iframe', false, "data-width='95%'");
|
||||
}
|
||||
|
||||
if($caseFails > 0) common::printIcon('testcase', 'createBug', "product=$case->product&branch=$case->branch&extra=caseID=$case->id,version=$case->version,runID=$runID", $case, 'button', 'bug', '', 'iframe', '', "data-width='90%'");
|
||||
}
|
||||
if($config->testcase->needReview or !empty($config->testcase->forceReview)) common::printIcon('testcase', 'review', "caseID=$case->id", $case, 'button', '', '', 'iframe', '', '', $lang->testcase->reviewAB);
|
||||
?>
|
||||
|
||||
<?php $case->isLibCase = $isLibCase;?>
|
||||
<?php $case->caseFails = $caseFails;?>
|
||||
<?php $case->runID = $runID;?>
|
||||
<?php echo $this->buildOperateMenu($case, 'view');?>
|
||||
|
||||
<?php
|
||||
if(!isonlybody()) common::printIcon('testcase', 'edit',"caseID=$case->id", $case, 'button', '', '', 'showinonlybody');
|
||||
if(!$isLibCase and $case->auto != 'unit') common::printIcon('testcase', 'create', "productID=$case->product&branch=$case->branch&moduleID=$case->module&from=testcase¶m=$case->id", $case, 'button', 'copy');
|
||||
if($isLibCase and common::hasPriv('caselib', 'createCase')) echo html::a($this->createLink('caselib', 'createCase', "libID=$case->lib&moduleID=$case->module¶m=$case->id"), "<i class='icon-copy'></i>", '', "class='btn' title='{$lang->testcase->copy}'");
|
||||
common::printIcon('testcase', 'delete', "caseID=$case->id", $case, 'button', 'trash', 'hiddenwin', '');
|
||||
?>
|
||||
<?php elseif($case->needconfirm):?>
|
||||
<?php common::printIcon('testcase', 'confirmstorychange', "caseID=$case->id", $case, 'list', 'confirm', 'hiddenwin', '', '', '', $this->lang->confirm);?>
|
||||
<?php endif;?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -327,4 +327,27 @@ class testsuiteModel extends model
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build testsuite menu.
|
||||
*
|
||||
* @param object $suite
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildOperateMenu($suite, $type = 'view')
|
||||
{
|
||||
$menu = '';
|
||||
$params = "suiteID=$suite->id";
|
||||
|
||||
if($type == 'view') $menu .= $this->buildFlowMenu('testsuite', $suite, $type, 'direct');
|
||||
|
||||
$menu .= $this->buildMenu('testsuite', 'linkCase', $params, $suite, $type, 'link', '', '', '', '', $this->lang->testsuite->linkCase);
|
||||
$menu .= $this->buildMenu('testsuite', 'edit', $params, $suite, $type);
|
||||
$menu .= $this->buildMenu('testsuite', 'delete', $params, $suite, $type, 'trash', 'hiddenwin');
|
||||
|
||||
return $menu;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,11 +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
|
||||
common::printIcon('testsuite', 'linkCase', "suiteID=$suite->id", $suite, 'list', 'link');
|
||||
common::printIcon('testsuite', 'edit', "suiteID=$suite->id", $suite, 'list');
|
||||
common::printIcon('testsuite', 'delete', "suiteID=$suite->id", $suite, 'list', 'trash', 'hiddenwin');
|
||||
?>
|
||||
<?php echo $this->buildOperateMenu($suite, 'browse');?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
|
||||
@@ -32,10 +32,6 @@
|
||||
if(!$suite->deleted and $canBeChanged)
|
||||
{
|
||||
echo $this->buildOperateMenu($suite, 'view');
|
||||
|
||||
common::printLink('testsuite', 'linkCase', "suiteID=$suite->id", "<i class='icon icon-link'> </i> " . '', '', "class='btn btn-link' title='{$lang->testsuite->linkCase}'");
|
||||
common::printIcon('testsuite', 'edit', "suiteID=$suite->id");
|
||||
common::printIcon('testsuite', 'delete', "suiteID=$suite->id", '', 'button', 'trash', 'hiddenwin');
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
@@ -2166,4 +2166,76 @@ class testtaskModel extends model
|
||||
|
||||
return array('suites' => $suites, 'cases' => $cases, 'results' => $results, 'suiteNames' => $suiteNames, 'caseTitles' => $caseTitles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build test 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 test task view menu.
|
||||
*
|
||||
* @param object $task
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildOperateViewMenu($task)
|
||||
{
|
||||
if($task->deleted) return '';
|
||||
|
||||
$menu = '';
|
||||
$params = "taskID=$task->id";
|
||||
|
||||
$menu .= $this->buildMenu('testtask', 'start', $params, $task, 'view', '', '', 'iframe showinonlybody', true);
|
||||
$menu .= $this->buildMenu('testtask', 'close', $params, $task, 'view', '', '', 'iframe showinonlybody', true);
|
||||
$menu .= $this->buildMenu('testtask', 'block', $params, $task, 'view', 'pause', '', 'iframe showinonlybody', true);
|
||||
$menu .= $this->buildMenu('testtask', 'activate', $params, $task, 'view', 'magic', '', 'iframe showinonlybody', true);
|
||||
$menu .= $this->buildMenu('testtask', 'cases', $params, $task, 'view', 'sitemap');
|
||||
$menu .= $this->buildMenu('testtask', 'linkCase', $params, $task, 'view', 'link');
|
||||
|
||||
$menu .= "<div class='divider'></div>";
|
||||
$menu .= $this->buildFlowMenu('testtask', $task, 'view', 'direct');
|
||||
$menu .= "<div class='divider'></div>";
|
||||
|
||||
$menu .= $this->buildMenu('testtask', 'edit', $params, $task, 'view');
|
||||
$menu .= $this->buildMenu('testtask', 'delete', $params, $task, 'view', 'trash', 'hiddenwin');
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build test task browse menu.
|
||||
*
|
||||
* @param object $task
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildOperateBrowseMenu($task)
|
||||
{
|
||||
$menu = '';
|
||||
$params = "taskID=$task->id";
|
||||
|
||||
$menu .= '<div id="action-divider">';
|
||||
$menu .= $this->buildMenu('testtask', 'cases', $params, $task, 'browse', 'sitemap');
|
||||
$menu .= $this->buildMenu('testtask', 'linkCase', "$params&type=all¶m=myQueryID", $task, 'browse', 'link');
|
||||
$menu .= $this->buildMenu('testreport', 'browse', "objectID=$task->product&objectType=product&extra=$task->id", $task, 'browse', 'flag');
|
||||
$menu .= '</div>';
|
||||
$menu .= $this->buildMenu('testtask', 'view', $params, $task, 'browse', 'list-alt', '', 'iframe', true, "data-width='90%'");
|
||||
$menu .= $this->buildMenu('testtask', 'edit', $params, $task, 'browse');
|
||||
if(common::hasPriv('testtask', 'delete', $task))
|
||||
{
|
||||
$deleteURL = helper::createLink('testtask', 'delete', "taskID=$task->id&confirm=yes");
|
||||
$menu .= html::a("javascript:ajaxDelete(\"$deleteURL\",\"taskList\",confirmDelete)", '<i class="icon-common-delete icon-trash"></i>', '', "title='{$this->lang->testtask->delete}' class='btn'");
|
||||
}
|
||||
return $menu;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,20 +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 '<div id="action-divider">';
|
||||
common::printIcon('testtask', 'cases', "taskID=$task->id", $task, 'list', 'sitemap');
|
||||
common::printIcon('testtask', 'linkCase', "taskID=$task->id&type=all¶m=myQueryID", $task, 'list', 'link');
|
||||
common::printIcon('testreport', 'browse', "objectID=$task->product&objectType=product&extra=$task->id", $task, 'list', 'flag');
|
||||
echo '</div>';
|
||||
common::printIcon('testtask', 'view', "taskID=$task->id", '', 'list', 'list-alt', '', 'iframe', true, "data-width='90%'");
|
||||
common::printIcon('testtask', 'edit', "taskID=$task->id", $task, 'list');
|
||||
if(common::hasPriv('testtask', 'delete', $task))
|
||||
{
|
||||
$deleteURL = $this->createLink('testtask', 'delete', "taskID=$task->id&confirm=yes");
|
||||
echo html::a("javascript:ajaxDelete(\"$deleteURL\",\"taskList\",confirmDelete)", '<i class="icon-common-delete icon-trash"></i>', '', "title='{$lang->testtask->delete}' class='btn'");
|
||||
}
|
||||
?>
|
||||
<?php echo $this->buildOperateMenu($task, 'browse');?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
|
||||
@@ -50,25 +50,8 @@
|
||||
<div class='main-actions'>
|
||||
<div class="btn-toolbar">
|
||||
<?php echo html::backButton('<i class="icon icon-back icon-sm"></i> ' . $lang->goback, '', 'btn btn-secondary');?>
|
||||
<?php if(!$task->deleted):?>
|
||||
<div class='divider'></div>
|
||||
<?php
|
||||
common::printIcon('testtask', 'start', "taskID=$task->id", $task, 'button', '', '', 'iframe showinonlybody', true);
|
||||
common::printIcon('testtask', 'close', "taskID=$task->id", $task, 'button', '', '', 'iframe showinonlybody', true);
|
||||
common::printIcon('testtask', 'block', "taskID=$task->id", $task, 'button', 'pause', '', 'iframe showinonlybody', true);
|
||||
common::printIcon('testtask', 'activate', "taskID=$task->id", $task, 'button', 'magic', '', 'iframe showinonlybody', true);
|
||||
common::printIcon('testtask', 'cases', "taskID=$task->id", $task, 'button', 'sitemap');
|
||||
common::printIcon('testtask', 'linkCase', "taskID=$task->id", $task, 'button', 'link');
|
||||
?>
|
||||
|
||||
<?php echo $this->buildOperateMenu($task, 'view');?>
|
||||
|
||||
<div class='divider'></div>
|
||||
<?php
|
||||
common::printIcon('testtask', 'edit', "taskID=$task->id", $task);
|
||||
common::printIcon('testtask', 'delete', "taskID=$task->id", $task, 'button', 'trash', 'hiddenwin');
|
||||
?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
sonar.projectKey=zentaopms
|
||||
sonar.qualitygate.wait=true
|
||||
sonar.coverage.exclusions=**/*.*
|
||||
@@ -0,0 +1,299 @@
|
||||
<?php
|
||||
class mailTest
|
||||
{
|
||||
/**
|
||||
* __construct.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
global $tester;
|
||||
global $dao;
|
||||
$this->dao = $dao;
|
||||
$this->tester = $tester;
|
||||
$this->objectModel = $tester->loadModel('mail');
|
||||
}
|
||||
|
||||
/**
|
||||
* AutoDetect.
|
||||
*
|
||||
* @param int $email
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function autoDetectTest($email)
|
||||
{
|
||||
$objects = $this->objectModel->autoDetect($email);
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
if(!$objects->host) return '没有检测到相关信息';
|
||||
|
||||
return $objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config from provider.
|
||||
*
|
||||
* @param int $domain
|
||||
* @param int $username
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getConfigFromProviderTest($domain, $username)
|
||||
{
|
||||
$object = $this->objectModel->getConfigFromProvider($domain, $username);
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config by MXRR.
|
||||
*
|
||||
* @param int $domain
|
||||
* @param int $username
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getConfigByMXRRTest($domain, $username)
|
||||
{
|
||||
$object = $this->objectModel->getConfigByMXRR($domain, $username);
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config by detecting SMTP.
|
||||
*
|
||||
* @param int $domain
|
||||
* @param int $username
|
||||
* @param int $port
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getConfigByDetectingSMTPTest($domain, $username, $port)
|
||||
{
|
||||
$object = $this->objectModel->getConfigByDetectingSMTP($domain, $username, $port);
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set MTA.
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function setMTATest()
|
||||
{
|
||||
$object = $this->objectModel->setMTA();
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set sendmail.
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function setSendMailTest()
|
||||
{
|
||||
$object = $this->objectModel->setSendMail();
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send.
|
||||
*
|
||||
* @param int $toList
|
||||
* @param int $subject
|
||||
* @param string $body
|
||||
* @param string $ccList
|
||||
* @param int $includeMe
|
||||
* @param array $emails
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function sendTest($toList, $subject, $body = '', $ccList = '', $includeMe = false, $emails = array())
|
||||
{
|
||||
$object = $this->objectModel->send($toList, $subject, $body, $ccList, $includeMe, $emails);
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set CC.
|
||||
*
|
||||
* @param int $ccList
|
||||
* @param int $emails
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function setCCTest($ccList, $emails)
|
||||
{
|
||||
$this->objectModel->setCC($ccList, $emails);
|
||||
|
||||
return $this->setMTATest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set subject.
|
||||
*
|
||||
* @param int $subject
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function setSubjectTest($subject)
|
||||
{
|
||||
$this->objectModel->setSubject($subject);
|
||||
|
||||
return $this->setMTATest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set body.
|
||||
*
|
||||
* @param int $body
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function setBodyTest($body)
|
||||
{
|
||||
$this->objectModel->setBody($body);
|
||||
|
||||
return $this->setMTATest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mail exist.
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function mailExistTest()
|
||||
{
|
||||
$object = $this->objectModel->mailExist();
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add queue.
|
||||
*
|
||||
* @param int $toList
|
||||
* @param int $subject
|
||||
* @param string $body
|
||||
* @param string $ccList
|
||||
* @param int $includeMe
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function addQueueTest($toList, $subject, $body = '', $ccList = '', $includeMe = false)
|
||||
{
|
||||
$this->objectModel->addQueue($toList, $subject, $body, $ccList, $includeMe);
|
||||
|
||||
if($toList and $subject)
|
||||
{
|
||||
$id = $this->dao->lastInsertID();
|
||||
$object = $this->dao->select('*')->from(TABLE_NOTIFY)->where('id')->eq($id)->fetch();
|
||||
}
|
||||
|
||||
if(!$object) return '没有数据提交';
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get queue.
|
||||
*
|
||||
* @param string $status
|
||||
* @param string $orderBy
|
||||
* @param int $pager
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getQueueTest($status = '', $orderBy = 'id_desc', $pager = null)
|
||||
{
|
||||
$objects = $this->objectModel->getQueue($status = '', $orderBy = 'id_desc', $pager = null);
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get queue by id.
|
||||
*
|
||||
* @param int $queueID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getQueueByIdTest($queueID)
|
||||
{
|
||||
$object = $this->objectModel->getQueueById($queueID);
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge mails.
|
||||
*
|
||||
* @param int $user
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function mergeMailsTest($user)
|
||||
{
|
||||
$mails = $this->dao->select('*')->from(TABLE_NOTIFY)
|
||||
->where('objectType')->eq('mail')
|
||||
->andWhere('toList')->eq($user)
|
||||
->fetchAll();
|
||||
|
||||
$object = $this->objectModel->mergeMails($mails);
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subject.
|
||||
*
|
||||
* @param int $objectType
|
||||
* @param int $object
|
||||
* @param int $title
|
||||
* @param int $actionType
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getSubjectTest($objectType, $object, $title, $actionType)
|
||||
{
|
||||
$object = $this->tester->loadModel($objectType)->getByID($object);
|
||||
$object = $this->objectModel->getSubject($objectType, $object, $title, $actionType);
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -80,9 +80,9 @@ fields:
|
||||
note: "邮箱"
|
||||
fields:
|
||||
- field: email1
|
||||
range: 100-999:R
|
||||
range: 1000-9999:2
|
||||
- field: email2
|
||||
range: 100-999:R
|
||||
range: 1000-9999:2
|
||||
- field: email3
|
||||
range: [@qq.com,@163.com,@gmail.com]
|
||||
- field: skype
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->addQueue();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
$result1 = $mail->addQueueTest('','');
|
||||
$result2 = $mail->addQueueTest('user3', '测试提交队列', '测试发信内容');
|
||||
$result3 = $mail->addQueueTest('user3,admin', '测试提交队列', '测试发信内容');
|
||||
$result4 = $mail->addQueueTest('user3,admin', '测试提交队列', '测试发信内容', '', true);
|
||||
|
||||
r($result1) && p() && e('没有数据提交'); //提交数据为空时
|
||||
r($result2) && p('subject') && e('测试提交队列'); //获取添加的邮件主题
|
||||
r($result3) && p('toList') && e('user3'); //获取收件人列表不包含自己
|
||||
r($result4) && p('toList') && e('user3,admin'); //获取收件人列表包含自己
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->autoDetect();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
$data = array('test@qq.com', 'test@163.com', 'test@sohu.com', 'test@vip.sohu.com', 'testm');
|
||||
|
||||
r($mail->autoDetectTest($data[0])) && p('host') && e('smtp.qq.com'); //检测qq邮箱信息
|
||||
r($mail->autoDetectTest($data[1])) && p('host') && e('smtp.163.com'); //检测163邮箱信息
|
||||
r($mail->autoDetectTest($data[2])) && p('host') && e('smtp.sohu.com'); //检测搜狐邮箱信息
|
||||
r($mail->autoDetectTest($data[3])) && p('host') && e('smtp.vip.sohu.com'); //检测搜狐vip邮箱信息
|
||||
r($mail->autoDetectTest($data[4])) && p() && e('没有检测到相关信息'); //检测不存在的邮箱服务商信息
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->getConfigByDetectingSMTP();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
$result1 = $mail->getConfigByDetectingSMTPTest('qq.com','122@qq.com',465);
|
||||
$result2 = $mail->getConfigByDetectingSMTPTest('qq.com','122@qq.com',465);
|
||||
$result3 = $mail->getConfigByDetectingSMTPTest('qq.com','122@qq.com',22);
|
||||
$result4 = $mail->getConfigByDetectingSMTPTest('testqq.com','122@qq.com',22);
|
||||
|
||||
r($result1) && p('host') && e('smtp.qq.com'); //根据域名获取smtp
|
||||
r($result2) && p('secure') && e('ssl'); //根据域名获取secure
|
||||
r($result3) && p('secure') && e('0'); //当端口号不为465时获取secure
|
||||
r($result4) && p() && e('0'); //当域名不存在时
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->getConfigByMXRR();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
$result1 = $mail->getConfigByMXRRTest('qq.com','test');
|
||||
$result2 = $mail->getConfigByMXRRTest('sohu.com','test');
|
||||
|
||||
r($result1) && p('host') && e('smtp.qq.com'); //获取qq相关信息
|
||||
r($result2) && p('host') && e('smtp.sohu.com'); //获取sohu相关信息
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->getConfigFromProvider();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
$result1 = $mail->getConfigFromProviderTest('qq.com','123');
|
||||
$result2 = $mail->getConfigFromProviderTest('sohu.com','123');
|
||||
|
||||
r($result1) && p('host') && e('smtp.qq.com'); //获取qq相关信息
|
||||
r($result2) && p('host') && e('smtp.sohu.com'); //获取sohu相关信息
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->getQueue();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
$result1 = count($mail->getQueueTest());
|
||||
$result2 = count($mail->getQueueTest('fail'));
|
||||
$result3 = count($mail->getQueueTest('wait'));
|
||||
$result4 = $mail->getQueueTest('wait');
|
||||
|
||||
r($result1) && p() && e('7'); //按照收件人分组获取邮件列表个数
|
||||
r($result2) && p() && e('7'); //按照收件人分组获取发送失败的邮件数量
|
||||
r($result3) && p() && e('7'); //按照收件人分组获取待发送的邮件数量
|
||||
r($result4) && p('0:data') && e('测试发信内容'); //按照收件人分组获取第一条待发送的邮件内容
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->getQueueById();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
$queueID = array(1,10,0);
|
||||
|
||||
r($mail->getQueueByIdTest($queueID[0])) && p('subject') && e('主题1'); //获取id为1的邮件主题
|
||||
r($mail->getQueueByIdTest($queueID[1])) && p('toList') && e('top10'); //获取id为10的收件人
|
||||
r($mail->getQueueByIdTest($queueID[2])) && p() && e('0'); //获取id不存在的邮件信息
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->getSubject();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
$result1 = $mail->getSubjectTest('testtask', 1, '123', 'closed');
|
||||
$result2 = $mail->getSubjectTest('doc', 1, 'test', 'created');
|
||||
$result3 = $mail->getSubjectTest('story', 1, 'test', 'created');
|
||||
$result4 = $mail->getSubjectTest('task', 1, 'test', 'created');
|
||||
$result5 = $mail->getSubjectTest('bug', 1, 'test', 'created');
|
||||
|
||||
r($result1) && p() && e('admin关闭了测试单 #1:测试单1'); //获取关闭测试单时邮件主题
|
||||
r($result2) && p() && e('admin创建了文档 #1:文档标题901'); //获取创建文档时的邮件主题
|
||||
r($result3) && p() && e('STORY #1 test - 正常产品1'); //获取操作需求时的邮件主题
|
||||
r($result4) && p() && e('TASK #1 test - 迭代1'); //获取操作任务时的邮件主题
|
||||
r($result5) && p() && e('BUG #1 test - 正常产品1'); //获取操作BUG时的邮件主题
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->mailExist();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
r($mail->mailExistTest()) && p('email') && e('10001000@qq.com'); //检查系统是否至少存在邮件
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->mergeMails();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
r($mail->mergeMailsTest('admin')) && p('id') && e('6,1'); //获取邮件合并后的id
|
||||
r($mail->mergeMailsTest('admin')) && p('subject') && e('主题6|主题1'); //获取邮件合并后的主题
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->send();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
/* If you don't set SMTP Please input you SMTP setting. */
|
||||
$mailConfig = new stdclass();
|
||||
$mailConfig->smtp = new stdclass();
|
||||
|
||||
$mailConfig->turnon = 1;
|
||||
$mailConfig->mta = 'smtp';
|
||||
$mailConfig->async = 0;
|
||||
$mailConfig->fromAddress = '';
|
||||
$mailConfig->fromName = '';
|
||||
$mailConfig->domain = '';
|
||||
$mailConfig->smtp->host = '';
|
||||
$mailConfig->smtp->port = '';
|
||||
$mailConfig->smtp->auth = '1';
|
||||
$mailConfig->smtp->username = '';
|
||||
$mailConfig->smtp->password = '';
|
||||
$mailConfig->smtp->secure = '';
|
||||
$mailConfig->smtp->debug = 1;
|
||||
$mailConfig->smtp->charset = 'utf-8';
|
||||
|
||||
global $tester;
|
||||
if(!isset($tester->config->mail->turnon)) $tester->loadModel('setting')->setItems('system.mail', $mailConfig);
|
||||
|
||||
$result1 = $mail->sendTest('admin','test','test','',true);
|
||||
|
||||
r($result1) && p() && e('0');
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->sendmail();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
r($mail->sendmailTest(48,48)) && p() && e('0'); //测试为dev4用户发送邮件通知
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->setCC();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
r($mail->setBodyTest('test body')) && p('Body') && e('test body'); //测试设置内容
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->setCC();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
r($mail->setMTATest()) && p('Host') && e('localhost'); //获取MTA主机
|
||||
r($mail->setMTATest()) && p('SMTPDebug') && e('0'); //获取MTAdebug设置
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/mail.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 mailModel->setCC();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
*/
|
||||
|
||||
$mail = new mailTest();
|
||||
|
||||
r($mail->setSubjectTest('test subject')) && p('Subject') && e('test subject'); //测试设置主题
|
||||
@@ -153,6 +153,9 @@ switch($argv[1])
|
||||
case 'tutorial':
|
||||
ztfRun('model/tutorial');
|
||||
break;
|
||||
case 'mail':
|
||||
ztfRun('model/mail');
|
||||
break;
|
||||
case 'tree':
|
||||
ztfRun('model/tree');
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user