Merge branch 'master' into 'zentaopms_wangyuting'

# Conflicts:
#   module/programplan/view/gantt.html.php
This commit is contained in:
王怡栋
2023-02-08 08:30:14 +00:00
90 changed files with 4922 additions and 157 deletions
+1 -1
View File
@@ -1 +1 @@
18.0
18.1
+3
View File
@@ -78,6 +78,9 @@ class hostHeartbeatEntry extends baseEntry
'status' => $vm->status,
'extranet' => $vm->ip,
);
if(!$vm->sshPortOnHost) unset($vmData['ssh']);
if($heartbeat > 0) $vmData['heartbeat'] = date("Y-m-d H:i:s", $heartbeat);
$this->dao->update(TABLE_ZAHOST)->data($vmData)->where('mac')->eq($vm->macAddress)->exec();
+11 -2
View File
@@ -23,7 +23,7 @@ class hostSubmitEntry extends baseEntry
/* Check authorize. */
$header = getallheaders();
$token = isset($header['Authorization']) ? substr($header['Authorization'], 7) : '';
// if(!$token) return $this->sendError(401, 'Unauthorized');
if(!$token) return $this->sendError(401, 'Unauthorized');
$now = helper::now();
@@ -38,7 +38,16 @@ class hostSubmitEntry extends baseEntry
->andWhere('tokenTime')->gt($now)->fi()
->fetch('id');
// if(!$id) return $this->sendError(400, 'Secret error.');
if(!$id) return $this->sendError(400, 'Secret error.');
$imageInfo = $this->dao->select('`status`,`from`')->from(TABLE_IMAGE)
->where('id')->eq($task)
->fetch();
if(empty($imageInfo)) return $this->sendSuccess(200, 'success');
if($imageInfo->from == 'snapshot' && $imageInfo->status == 'restoring')
{
$image->status = $image->status == 'completed' ? 'restore_completed' : 'restore_failed';
}
$this->dao->update(TABLE_IMAGE)->data($image)->where("id")->eq($task)->exec();
+1 -1
View File
@@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}}
if(!function_exists('getWebRoot')){function getWebRoot(){}}
/* 基本设置。Basic settings. */
$config->version = '18.0'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->version = '18.1'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->liteVersion = '1.2'; // 迅捷版版本。 The version of Lite.
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
+4 -3
View File
@@ -227,7 +227,7 @@ $config->openMethods[] = 'doc.createbasicinfo';
$config->openMethods[] = 'project.createguide';
$config->openMethods[] = 'task.editteam';
$config->openMethods[] = 'feedback.mergeproductmodule';
$config->openMethods[] = 'zahost.introduction';
$config->openMethods[] = 'zanode.list';
$config->openModules = array();
$config->openModules[] = 'install';
@@ -404,8 +404,9 @@ $config->objectTables['stage'] = TABLE_STAGE;
$config->objectTables['apistruct'] = TABLE_APISTRUCT;
$config->objectTables['repo'] = TABLE_REPO;
$config->objectTables['dataview'] = TABLE_DATAVIEW;
$config->objectTables['zahost'] = TABLE_ZAHOST;
$config->objectTables['automation'] = TABLE_AUTOMATION;
$config->objectTables['zahost'] = TABLE_ZAHOST;
$config->objectTables['automation'] = TABLE_AUTOMATION;
$config->objectTables['stepResult'] = TABLE_TESTRUN;
$config->newFeatures = array('introduction', 'tutorial', 'youngBlueTheme', 'visions');
$config->disabledFeatures = '';
File diff suppressed because it is too large Load Diff
+6 -1
View File
@@ -1,3 +1,9 @@
ALTER TABLE `zt_host` ADD `type` varchar(30) NOT NULL DEFAULT 'normal' AFTER `admin`;
ALTER TABLE `zt_host` ADD `secret` varchar(50) NOT NULL DEFAULT '' AFTER `type`;
ALTER TABLE `zt_host` ADD `token` varchar(50) NOT NULL DEFAULT '' AFTER `secret`;
ALTER TABLE `zt_host` ADD `expiredDate` datetime NOT NULL AFTER `token`;
ALTER TABLE `zt_host` ADD `virtualSoftware` varchar(30) NOT NULL DEFAULT '' AFTER `expiredDate`;
ALTER TABLE `zt_host`
DROP COLUMN `cabinet`,
DROP COLUMN `cpuRate`,
@@ -58,7 +64,6 @@ h.`createdDate` = a.`createdDate`,
h.`editedBy` = a.`editedBy`,
h.`editedDate` = a.`editedDate`,
h.`group` = a.`group`,
h.`type` = a.`type`,
h.`deleted` = a.`deleted`
WHERE
h.`assetID` = a.`id`;
+3
View File
@@ -1 +1,4 @@
ALTER TABLE `zt_image` ADD `localName` VARCHAR(64) NOT NULL AFTER `name`;
ALTER TABLE `zt_image` ADD `restoreDate` datetime NOT NULL AFTER `createdDate`;
ALTER TABLE `zt_ticket` MODIFY `resolution` text NOT NULL;
+33 -17
View File
@@ -4081,23 +4081,39 @@ REPLACE INTO `zt_lang` (`lang`, `module`, `section`, `key`, `value`, `system`) V
('all', 'process', 'classify', 'engineering', '工程支持', '1'),
('all', 'process', 'classify', 'project', '项目管理', '1');
REPLACE INTO `zt_process` (`id`, `name`, `type`, `abbr`, `desc`, `assignedTo`, `status`, `order`, `createdBy`, `createdDate`, `editedBy`, `editedDate`, `assignedBy`, `assignedDate`, `deleted`) VALUES
(11,'立项管理','project','PIM','','','',55,'admin','2020-01-09 10:29:55','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(12,'项目规划','project','PP','','','',60,'admin','2020-01-09 10:31:16','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(13,'项目监控','project','PMC','','','',65,'admin','2020-01-09 10:31:16','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(14,'风险管理','project','RSKM','','','',70,'admin','2020-01-09 10:31:16','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(15,'结项管理','project','PCM','','','',75,'admin','2020-01-09 10:31:16','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(16,'量化项目管理','project','QPM','','','',80,'admin','2020-01-09 10:31:16','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(17,'需求开发','engineering','RDM','','','',85,'admin','2020-01-09 13:14:55','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(18,'设计开发','engineering','','','','',90,'admin','2020-01-09 13:14:55','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(19,'实现与测试','engineering','EMBEDDED','','','',95,'admin','2020-01-09 13:14:55','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(20,'系统测试','engineering','ST','','','',100,'admin','2020-01-09 13:14:55','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(21,'客户验收','engineering','CA','','','',105,'admin','2020-01-09 13:14:55','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(22,'质量保证','support','QA','','','',110,'admin','2020-01-09 13:14:55','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(23,'配置管理','support','CM','','','',115,'admin','2020-01-09 13:14:55','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(24,'度量分析','support','MA','','','',120,'admin','2020-01-09 13:14:55','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(25,'原因分析与解决','support','CAR','','','',125,'admin','2020-01-09 13:14:55','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0'),
(26,'决策分析','support','DAR','','','',130,'admin','2020-01-09 13:14:55','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0');
REPLACE INTO `zt_process` (`id`, `model`, `name`, `type`, `abbr`, `desc`, `assignedTo`, `status`, `order`, `createdBy`, `createdDate`, `editedBy`, `editedDate`, `assignedBy`, `assignedDate`, `deleted`) VALUES
(11, 'waterfall', '立项管理', 'project', 'PIM', '', '', '', 55, 'admin', '2020-01-09 10:29:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(12, 'waterfall', '项目规划', 'project', 'PP', '', '', '', 60, 'admin', '2020-01-09 10:31:16', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(13, 'waterfall', '项目监控', 'project', 'PMC', '', '', '', 65, 'admin', '2020-01-09 10:31:16', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(14, 'waterfall', '风险管理', 'project', 'RSKM', '', '', '', 70, 'admin', '2020-01-09 10:31:16', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(15, 'waterfall', '结项管理', 'project', 'PCM', '', '', '', 75, 'admin', '2020-01-09 10:31:16', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(16, 'waterfall', '量化项目管理', 'project', 'QPM', '', '', '', 80, 'admin', '2020-01-09 10:31:16', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(17, 'waterfall', '需求开发', 'engineering', 'RDM', '', '', '', 85, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(18, 'waterfall', '设计开发', 'engineering', '', '', '', '', 90, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(19, 'waterfall', '实现与测试', 'engineering', 'EMBEDDED', '', '', '', 95, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(20, 'waterfall', '系统测试', 'engineering', 'ST', '', '', '', 100, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(21, 'waterfall', '客户验收', 'engineering', 'CA', '', '', '', 105, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(22, 'waterfall', '质量保证', 'support', 'QA', '', '', '', 110, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(23, 'waterfall', '配置管理', 'support', 'CM', '', '', '', 115, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(24, 'waterfall', '度量分析', 'support', 'MA', '', '', '', 120, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(25, 'waterfall', '原因分析与解决', 'support', 'CAR', '', '', '', 125, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(26, 'waterfall', '决策分析', 'support', 'DAR', '', '', '', 130, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(41, 'scrum', '原因分析与解决', 'support', 'CAR', '', '', '', 125, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(40, 'scrum', '度量分析', 'support', 'MA', '', '', '', 120, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(39, 'scrum', '配置管理', 'support', 'CM', '', '', '', 115, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(38, 'scrum', '质量保证', 'support', 'QA', '', '', '', 110, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(37, 'scrum', '客户验收', 'engineering', 'CA', '', '', '', 105, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(36, 'scrum', '系统测试', 'engineering', 'ST', '', '', '', 100, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(35, 'scrum', '实现与测试', 'engineering', 'EMBEDDED', '', '', '', 95, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(34, 'scrum', '设计开发', 'engineering', '', '', '', '', 90, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(33, 'scrum', '需求开发', 'engineering', 'RDM', '', '', '', 85, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(32, 'scrum', '量化项目管理', 'project', 'QPM', '', '', '', 80, 'admin', '2020-01-09 10:31:16', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(31, 'scrum', '结项管理', 'project', 'PCM', '', '', '', 75, 'admin', '2020-01-09 10:31:16', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(30, 'scrum', '风险管理', 'project', 'RSKM', '', '', '', 70, 'admin', '2020-01-09 10:31:16', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(29, 'scrum', '项目监控', 'project', 'PMC', '', '', '', 65, 'admin', '2020-01-09 10:31:16', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(28, 'scrum', '项目规划', 'project', 'PP', '', '', '', 60, 'admin', '2020-01-09 10:31:16', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(27, 'scrum', '立项管理', 'project', 'PIM', '', '', '', 55, 'admin', '2020-01-09 10:29:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0'),
(42, 'scrum', '决策分析', 'support', 'DAR', '', '', '', 130, 'admin', '2020-01-09 13:14:55', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '0');
REPLACE INTO `zt_activity` (`id`, `process`, `name`, `optional`, `content`, `assignedTo`, `status`, `createdBy`, `createdDate`, `editedBy`, `editedDate`, `assignedBy`, `assignedDate`, `order`, `deleted`) VALUES
(4,11,'立项调查,可行性分析,技术预研','yes','','','','admin','2020-01-09 10:49:34','','0000-00-00 00:00:00','','0000-00-00 00:00:00',20,'0'),
+2
View File
@@ -7359,6 +7359,7 @@ CREATE TABLE `zt_image` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`host` int(11) unsigned NOT NULL DEFAULT 0,
`name` varchar(64) NOT NULL DEFAULT '',
`localName` varchar(64) NOT NULL DEFAULT '',
`address` varchar(64) NOT NULL DEFAULT '',
`path` varchar(64) NOT NULL DEFAULT '',
`status` varchar(20) NOT NULL DEFAULT '',
@@ -7371,6 +7372,7 @@ CREATE TABLE `zt_image` (
`desc` text NOT NULL,
`createdBy` varchar(30) NOT NULL,
`createdDate` datetime NOT NULL,
`restoreDate` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+235
View File
@@ -1,3 +1,238 @@
2023-02-08 18.1
完成的需求
开源版:
41313 解除需求和bug的关联后保持列表排序
40637 用例执行失败转Bug时,将结果附件带到bug创建页面中
41312 产品的项目列表种修改“我参与的”逻辑
33347 测试单按照需求关联用例的列表中增加关联需求字段
41209 运行自动化测试方案的示例测试
41623 优化自动化测试解决方案页面
41624 调整执行节点详情页中手册的跳转逻辑
41625 优化远程桌面执行节点页面
41626 优化宿主机初始化脚本
41210 还原执行节点快照
41215 创建执行节点快照
41423 浏览执行节点快照
41424 编辑执行节点快照
41425 删除执行节点快照
41818 调整宿主机和执行节点详情页面按钮禁用的样式
41819 将宿主机详情页面中的执行节点列表放到独立区块中
41820 执行节点详情页面默认密码密文显示
禅道客户端:
41193 实现系统群设置音视频是否开启的功能
40934 实现侧边栏会议模式优化
40933 实现协作文件发送入口优化
40932 实现协作文件编辑入口优化
40625 实现发言人动态排序
40548 实现共享屏幕时显示成员名称及开麦标识
40538 实现离开音视频会议时不再显示会议状态
40282 实现视频会议的开麦标识
40229 删除参会人员会议电话标识
40227 实现语音会议的开麦标识功能
40215 实现PPT文件的在线编辑功能
40214 实现音视频会议全屏显示优化
40205 实现定时清理消息列表上方的旧消息
40204 实现会议视频放大后侧边栏模式设计
40199 实现音视频会议展示顺序
40197 实现会议视频展示排版优化
40185 实现增加会议独立窗口邀请成员功能
40039 实现XXB后台可配置升级通知
39895 实现点对点文件传输断线增加提示
39841 实现禅道客户端全文搜索正常显示待选框
39833 实现无权访问禅道页面时链接跳转不显示重新登录界面
39831 实现无权访问禅道页面时不显示重新登录界面
39723 实现增加点对点文件重传功能
39722 实现会议通话与SRS/OWT断连处理
39721 实现会议通话与XXD断连处理
39720 实现音视频断线重连交互设计
39719 实现音视频断连情况下不要自动关闭窗口
39567 实现加快短暂离线时消息无法发送的提醒
39565 实现短暂离线时消息记录窗口不关闭
39563 实现短暂离线时独立文件窗口不关闭
39560 实现短暂离线时独立看图窗口不关闭
39557 实现优化XXD处理XXB输出数据问题
39554 实现喧喧白屏问题处理
39509 删除禅道客户端“签退”入口
39508 实现从会话中进入聊天记录时定位到最新的消息
39506 实现GIF动图复制功能
修复的Bug
31406 执行节点详情页点击SSH复制按钮复制信息不全
31336 执行节点执行休眠/恢复/关闭/启动/重启操作后对应的历史信息记录不正确
31348 宿主机详情页执行节点列表建议添加执行节点详情页跳转超链接
31329 英文语言项下宿主机详情页的执行节点列表字段显示不全
27651 bug搜索条件选择从属于某个模块,数据不正确
28463 全文检索无法按项目名称搜索项目
30787 权限列表有代码报错
30679 用户需求列表的操作栏显示不正确
31392 项目型项目中创建迭代,保存成功后提示导入计划关联的相关研发需求
30537 邮件列表中失败原因文案错误
30381 看板项目设置团队会提示迭代代号不能为空
30379 编辑看板项目,保存会提示代号不能为空
28513 通过URL链接访问项目需求时不能跳转到正确的项目
31403 无产品无执行项目的看板中提Bug模块加载不对
28516 激活后的需求再次变更无论评审结果如何状态均为“激活”
31343 计划的需求列表中批量编辑需求时所属计划信息丢失
28536 批量修改已解决Bug截止日期会联动修改解决日期
31359 创建完宿主机或者执行节点后,在跳转的详情页点击返回按钮又跳转回创建页面
28805 项目干系人无法查看到项目
28809 编辑任务工时后,工时数不正确
29999 无迭代项目Bug转任务时错误提示,转任务不成功
29118 看板卡片历史记录缺少语言项
29629 关闭用户需求后,研发需求自定义设置中可配置SR,UR字段
30267 创建测试类型任务选择研发需求,点击保存页面转圈后不能返回到列表页面
30289 关闭迭代代号后,编辑项目,保存时会提示:『迭代代号』不能为空。
30918 拥有全部权限的admin管理员无法对版本做操作
30401 bug编辑页面中,点击关联bug,弹窗中不加载数据
29956 无迭代项目下新建测试任务,保存后无法返回页面
31498 导出镜像成功后,提示文案需要调整更清晰
31493 导出镜像等候时间过长,需要加上提示文案
31432 执行节点已关闭,导出镜像时还提示需要关闭执行
31421 宿主机的执行节点排序查看时,整个页面刷新
31347 初次进入宿主机列表显示的架构图英文语言项下显示中文
31718 api反馈数据中teammember字段值全部为空
31948 按项目创建的瀑布项目,关联新的产品,阶段不会自动关联
26538 主机分组维护页面导航高亮错误
29380 甘特图页面进入任务编辑页面抄送给下拉样式问题
24928 后台自定义反馈页面代码报错
30382 地盘--日志,新增日志无法保存
24628 导入8个用户导入页面有报错
27438 计划详情页弹窗中需求名称未显示出来
26536 编辑主机页面代码报错
25723 升级后测试单关联的用例数据没有了
30452 进入工单页面1.5级会选中一个产品列表中显示全部产品的工单
24530 新增流程页面显示空白
30936 反馈转工单时同步产品模块后页面未返回到创建工单页面
31107 导出多分支产品Bug模板,系统数据中没有分支
31844 组织中查看所有人日志、待办不生效
30377 备份完成后不关闭备份弹窗,代码备份显示0个文件
30970 无产品无迭代项目下导出日志设置字段中显示了“执行”
30997 导入任务页面默认展示了相关研发需求
30939 反馈转多人任务后任务详情页样式问题
30904 反馈或工单转孪生需求,历史记录中只列出了ID最小的需求
30827 地盘新增日志-所属任务下拉无法搜索多人任务
31161 点击搜索结果的工单标题,提示无权访问
29348 工单后没显示数量
30111 反馈进行产品设置后,设置列表页产品数量统计错误
30064 分组视图导出弹窗样式需优化
29236 同时高亮了年度总结和透视表两个2级导航
28875 导出的需求模板中分支/平台下拉中没有数据
28765 显示设置为‘只显示最后一级模块’,但是标题仍然显示第一级模块。
28704 创建工单页面没有显示产品的1.5级下拉框
28799 反馈编辑页面,之前添加的附件没有带出
29244 处理中状态列表和详情页展示的颜色不一致
28272 产品需求导入评审者设置非评审人也可以导入成功
26875 显示设置中没有默认选中项
23754 英文下导出用例模板时按钮换行
28270 产品研发需求导出模板评审者错误
23817 反馈列表页滚动条被遮挡
23823 反馈列表在简单表格默认列表字段下有横向滑动条
22182 地盘-待处理-问题 没有【确认】按钮
22251 项目>评审>发起评审,添加附件>保存,附件没有保存到附件库
22299 审批流列表底部未显示数量统计和翻页控件
30834 通过编辑方式修改产品库文档所属于WIKI下的文档库时,该文档丢失。
22332 打基线和编辑基线页面必填标识显示不一致
22334 编辑基线必填校验显示异常
22335 会签评审流程一人评审后,该评审还是待评审状态
22389 问题库列表中列字段显示重叠
22494 项目问题转任务后,任务所属执行信息丢失,导致打开异常
22583 设计无法根据相关需求进行搜索
22598 查看评审节点和结果有横向滑动条
22599 取消选择后,保存成功但角色成员没清空
22606 基本度量项语言项缺失
22727 已取消的风险没法关闭
22742 执行过程裁剪执行按钮不对齐
22902 检查对象的下拉框遮挡所属过程下拉框
23097 提交评审动态中缺少中文语言项
23131 任务详情页面无法切换版本
23212 添加产品时添加白名单用户列表已填写内容消失
23515 评审的Markdown文档正文中换行丢失
23603 偶发性bug:点击导航中的执行,标题是执行,但是内容还停留在产品研发需求中
23529 发起评审页面缺少英文语言项
23532 评审页面,文档中的附件和评审附件位置颠倒
23640 在项目、执行点击某一个BUG详情,会显示到测试-BUG页面
23644 产品下拉列表顶部显示了空白
24224 需求库导入需求时筛选条件选择版本号搜索报错
23688 英文模式下,仪表盘最新动态报错
23753 访问执行的任务,导航不正确
23779 顶级导航菜单没有折叠显示
24306 活动详情弹窗中显示不全
24567 瀑布项目审批设置可以关联工作流审批
24695 导出测试报告,概况缺少部分内容
24713 问题库问题列表严重程度字段换行显示了
24716 最佳实践库/组件库导入时样式问题
24727 质量保证计划列表页简单表格下,底部滚动条被遮挡
24749 日程右侧更多下拉中选择测试单后样式不对
24755 markdown文档在资产库中没有显示为markdown格式
24772 项目搜索结果列表中无法正确点击打开项目
24871 风险详情中创建日期和编辑日期时间总是显示00:00:00
25156 问题页面无数据时,字体颜色跟其他模块不一致
25310 研发需求批量拆分的子需求自动进入已立项阶段
25339 用户需求细分的研发需求阶段显示为“已立项”
25612 任务详情页无法切换版本
25617 日志页面,部门字段应该显示具体的部门
25684 权限维护页面选择更多下的菜单后建议显示已选择的菜单名称
25413 切换估算单位保存成功后,提示有未提交的表单
25384 访问产品文档的附件库,提示没有所属产品权限
24603 创建审批流页面按钮未居中
24605 项目审批设置页面报错按钮未居中
25470 编辑质量保证计划时显示了已删除的过程
25634 后台敏捷模型中不能创建过程
25479 批量新建QA检查内容时页面样式错乱
25538 阶段的编辑页面增加负责人字段
25767 任务列表中状态显示不全
26127 Bug详情页的返回页面样式不正确
25623 创建人名字较长时,列表显示不规整
26030 会议记录页面附件名称较长时操作按钮换行显示了
25980 修改Bug解决版本,历史记录从版本中移除
25509 编辑已检查的质量保证计划,修改检查对象后检查结果报错
25702 内禅部分过程裁剪后仍可以创建计划
26040 会议记录页面重命名附件后再次上传附件保存时sql错误
26069 项目周报中项目成本计算所取的单位人工成本是后台数值而非项目所设
29669 瀑布项目中对提交审计的基线进行审计操作,修改后再次审计操作没有了
25460 地盘贡献评审列表中审批进度弹窗显示空白
24936 新建工作流中发起评审,评审后动态有报错
27332 已被删除的活动/文档还能建质量保证计划
28872 已删除评审问题详情页点击返回后二级导航缺失
31423 评审项目计划动态详情页面返回链接不对
24269 审批流程中设置评审人员直属上级后发起评审页面不显示
22634 发起评审时并行分支中角色的审批人员未显示
25991 阶段信息确认页面多个相同阶段的ID号重复显示
23527 重新发起评审,评审文档未更新
29766 瀑布项目结束后不应再继续计算挣值数据
28443 执行下创建/批量创建QA计划页面指派给与列表中指派给列出的用户不一致
24299 点击动态中的过程/活动/文档名称无法跳转
27199 点击动态中的已删除问题名称,跳转后页面报错
22608 自动通过评审时查看评审结果页面的评审人员为空
22614 审批人重复显示
22733 max2.5升级到max3.1beta1评审中的审批节点只显示待评审人
22814 项目审批撤销编辑之后无法选择评审人
31320 复制敏捷项目时切换步骤会提示连接超时
24665 升级到max3.3后,敏捷模型的文档列表显示了内置数据
20080 网络不好时加入会议失败,再次加入会议看不到屏幕分享
26805 同分组下合并会话报错
27082 群管理中demo数据加载不出群主
27414 登录账号admin提示登录不上
29109 聊天窗口最小化打开成员列表侧边栏查看按钮重叠
29115 群组操作菜单项出现双分割线
29425 用户状态为非在线时,在小喧喧输入搜人指令后,状态栏为空数据
29450 小喧喧会话框发送截图、文件返回错误信息
29475 小喧喧会话发送查看 任务发送失败
29506 账号接收禅道通知点击查看界面崩溃报错
29510 小喧喧未识别到包含大小写的指令
29536 禅道客户端的讨论组管理界面刷新不出来
29538 禅道客户端的群设置功能不能正常使用
29690 离线状态下用户点击“预览”文件弹窗报错
30023 内网禅道客户端登录后白屏需要二次登录才能正常显示
30083 消息卡片在列表存在不显示的情况
30084 存在偶发点击后没有跳转到相应会话的情况
30306 讨论组@相关成员后,草稿状态下,会展示用户ID
30370 xxd断连再重启,会议中的用户重新登录后,会议窗口关闭,会议结束
30372 反复开关闭视频会复制出多个卡片
30497 通过阿道发送完成任务指令,完成任务后,返回的工时记录中,消耗时间展示有误
30499 登录禅道客户端后,阿道机器人在聊天列表中的头像未展示
30509 阿道任务列表下,需要将父任务相关按钮置为只读
30514 禅道客户端机器人名称为:阿道@阿道
2023-01-03 18.0
完成的需求
开源版:
+2 -2
View File
@@ -16,10 +16,10 @@ $PHPMAILER_LANG['from_failed'] = 'Die folgende Absenderadresse ist nich
$PHPMAILER_LANG['instantiate'] = 'Mail Funktion konnte nicht initialisiert werden.';
$PHPMAILER_LANG['invalid_email'] = 'E-Mail wird nicht gesendet, die Adresse ist ungültig.';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer wird nicht unterstützt.';
$PHPMAILER_LANG['provide_address'] = 'Bitte geben Sie mindestens eine Empfänger E-Mailadresse an.';
$PHPMAILER_LANG['provide_address'] = 'The recipient has not set up an email address, please go to the background-personnel-user edit to add an email address.';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP Fehler: Die folgenden Empfänger sind nicht korrekt: ';
$PHPMAILER_LANG['signing'] = 'Fehler beim Signieren: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'Verbindung zu SMTP Server fehlgeschlagen.';
$PHPMAILER_LANG['smtp_error'] = 'Fehler vom SMTP Server: ';
$PHPMAILER_LANG['variable_set'] = 'Kann Variable nicht setzen oder zurücksetzen: ';
?>
?>
+2 -2
View File
@@ -16,10 +16,10 @@ $PHPMAILER_LANG['from_failed'] = 'L\'adresse d\'expéditeur suivante a
$PHPMAILER_LANG['instantiate'] = 'Impossible d\'instancier la fonction mail.';
//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' client de messagerie non supporté.';
$PHPMAILER_LANG['provide_address'] = 'Vous devez fournir au moins une adresse de destinataire.';
$PHPMAILER_LANG['provide_address'] = 'The recipient has not set up an email address, please go to the background-personnel-user edit to add an email address.';
$PHPMAILER_LANG['recipients_failed'] = 'Erreur SMTP : Les destinataires suivants sont en erreur : ';
//$PHPMAILER_LANG['signing'] = 'Signing Error: ';
//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
?>
?>
@@ -17,7 +17,7 @@ $PHPMAILER_LANG['from_failed'] = '发送地址错误:';
$PHPMAILER_LANG['instantiate'] = '未知函数调用。';
//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
$PHPMAILER_LANG['mailer_not_supported'] = '发信客户端不被支持。';
$PHPMAILER_LANG['provide_address'] = '收件人没有设置邮箱,请到组织视图中检查下相应用户的email设置。';
$PHPMAILER_LANG['provide_address'] = '收件人没有设置邮箱,请到后台-人员-用户编辑中添加上邮箱地址。';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP 错误:收件人地址错误,或检查SMTP服务设置,是否允许发送该邮件地址:';
//$PHPMAILER_LANG['signing'] = 'Signing Error: ';
//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
@@ -17,7 +17,7 @@ $PHPMAILER_LANG['from_failed'] = '發送地址錯誤:';
$PHPMAILER_LANG['instantiate'] = '未知函數調用。';
//$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
$PHPMAILER_LANG['mailer_not_supported'] = '發信客戶端不被支持。';
$PHPMAILER_LANG['provide_address'] = '收件人沒有設置郵箱,請到組織視圖中檢查下相應用戶的email設置。';
$PHPMAILER_LANG['provide_address'] = '收件人沒有設置郵箱,請到後台-人員-用戶編輯中添加上郵箱地址。';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP 錯誤:收件人地址錯誤,或檢查SMTP服務設置,是否允許發送該郵件地址:';
//$PHPMAILER_LANG['signing'] = 'Signing Error: ';
//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
+1
View File
@@ -49,6 +49,7 @@ $config->action->objectNameFields['stage'] = 'name';
$config->action->objectNameFields['apistruct'] = 'name';
$config->action->objectNameFields['repo'] = 'name';
$config->action->objectNameFields['dataview'] = 'name';
$config->action->objectNameFields['zahost'] = 'name';
$config->action->objectNameFields['zanode'] = 'name';
$config->action->commonImgSize = 870;
+8
View File
@@ -237,6 +237,10 @@ $lang->action->desc->relieved = '$date, relieved by <strong>$actor</
$lang->action->desc->switchtolight = '$date, Switch from ALM mode to light mode by <strong>'. $lang->admin->system .'</strong>.' . "\n";
$lang->action->desc->getvnc = '$date, Remote control <strong>$extra</strong> by <strong>$actor</strong> .' . "\n";
$lang->action->desc->unlinkproduct = '$date, the project is disassociated from the $extra, synchronization disassociates the ' . $lang->executionCommon . 's of the project from the $extra.' . "\n";
$lang->action->desc->createdsnapshot = '$date, <strong>$actor</strong> creates a snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->restoredsnapshot = '$date, <strong>$actor</strong> restored a snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->editsnapshot = '$date, <strong>$actor</strong> edited the snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->deletesnapshot = '$date, <strong>$actor</strong> deleted snapshot <strong>$extra</strong>。' . "\n";
/* Used to describe the history of operations related to parent-child tasks. */
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> created a child task <strong>$extra</strong>。' . "\n";
@@ -419,6 +423,10 @@ $lang->action->label->switchtolight = 'switch from ALM mode to light mod
$lang->action->label->linkedrepo = 'Linked Code Repo';
$lang->action->label->unlinkedrepo = 'Unlinked Code Repo';
$lang->action->label->unlinkproduct = 'Unlinked Product';
$lang->action->label->createdsnapshot = 'create snapshot';
$lang->action->label->restoredsnapshot = 'create snapshot';
$lang->action->label->editsnapshot = 'edit snapshot';
$lang->action->label->deletesnapshot = 'deleted snapshot';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass;
+8
View File
@@ -237,6 +237,10 @@ $lang->action->desc->relieved = '$date, relieved by <strong>$actor</
$lang->action->desc->switchtolight = '$date, Switch from ALM mode to light mode by <strong>'. $lang->admin->system .'</strong>.' . "\n";
$lang->action->desc->getvnc = '$date, Remote control <strong>$extra</strong> by <strong>$actor</strong> .' . "\n";
$lang->action->desc->unlinkproduct = '$date, the project is disassociated from the $extra, synchronization disassociates the ' . $lang->executionCommon . 's of the project from the $extra.' . "\n";
$lang->action->desc->createdsnapshot = '$date, <strong>$actor</strong> creates a snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->restoredsnapshot = '$date, <strong>$actor</strong> restored a snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->editsnapshot = '$date, <strong>$actor</strong> edited the snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->deletesnapshot = '$date, <strong>$actor</strong> deleted snapshot <strong>$extra</strong>。' . "\n";
/* Used to describe the history of operations related to parent-child tasks. */
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> created a child task <strong>$extra</strong>。' . "\n";
@@ -419,6 +423,10 @@ $lang->action->label->switchtolight = 'switch from ALM mode to light mod
$lang->action->label->linkedrepo = 'Linked Code Repo';
$lang->action->label->unlinkedrepo = 'Unlinked Code Repo';
$lang->action->label->unlinkproduct = 'Unlinked Product';
$lang->action->label->createdsnapshot = 'create snapshot';
$lang->action->label->restoredsnapshot = 'create snapshot';
$lang->action->label->editsnapshot = 'edit snapshot';
$lang->action->label->deletesnapshot = 'deleted snapshot';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass;
+8
View File
@@ -237,6 +237,10 @@ $lang->action->desc->relieved = '$date, relieved by <strong>$actor</
$lang->action->desc->switchtolight = '$date, Switch from ALM mode to light mode by <strong>'. $lang->admin->system .'</strong>.' . "\n";
$lang->action->desc->getvnc = '$date, Remote control <strong>$extra</strong> by <strong>$actor</strong> .' . "\n";
$lang->action->desc->unlinkproduct = '$date, the project is disassociated from the $extra, synchronization disassociates the ' . $lang->executionCommon . 's of the project from the $extra.' . "\n";
$lang->action->desc->createdsnapshot = '$date, <strong>$actor</strong> creates a snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->restoredsnapshot = '$date, <strong>$actor</strong> restored a snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->editsnapshot = '$date, <strong>$actor</strong> edited the snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->deletesnapshot = '$date, <strong>$actor</strong> deleted snapshot <strong>$extra</strong>。' . "\n";
/* Used to describe the history of operations related to parent-child tasks. */
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> a créé un sous-tâche <strong>$extra</strong>。' . "\n";
@@ -419,6 +423,10 @@ $lang->action->label->switchtolight = 'switch from ALM mode to light mod
$lang->action->label->linkedrepo = 'Linked Code Repo';
$lang->action->label->unlinkedrepo = 'Unlinked Code Repo';
$lang->action->label->unlinkproduct = 'Unlinked Product';
$lang->action->label->createdsnapshot = 'create snapshot';
$lang->action->label->restoredsnapshot = 'create snapshot';
$lang->action->label->editsnapshot = 'edit snapshot';
$lang->action->label->deletesnapshot = 'deleted snapshot';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass();
+8
View File
@@ -237,6 +237,10 @@ $lang->action->desc->relieved = '$date, 由 <strong>$actor</strong>
$lang->action->desc->switchtolight = '$date, 由于 <strong>'. $lang->admin->system .'</strong> 从全生命周期管理模式切换为轻量管理模式,项目访问控制由项目集内公开调整为私有。' . "\n";
$lang->action->desc->getvnc = '$date, <strong>$actor</strong>对执行节点 <strong>$extra</strong> 进行了远程操控。' . "\n";
$lang->action->desc->unlinkproduct = '$date, 系统判断由于' . $lang->executionCommon . '所属项目与$extra取消关联,同步将' . $lang->executionCommon . '与$extra取消关联。' . "\n";
$lang->action->desc->createdsnapshot = '$date, <strong>$actor</strong> 创建了快照 <strong>$extra</strong>。' . "\n";
$lang->action->desc->restoredsnapshot = '$date, <strong>$actor</strong> 还原了快照 <strong>$extra</strong>。' . "\n";
$lang->action->desc->editsnapshot = '$date, <strong>$actor</strong> 编辑了快照 <strong>$extra</strong>。' . "\n";
$lang->action->desc->deletesnapshot = '$date, <strong>$actor</strong> 删除了快照 <strong>$extra</strong>。' . "\n";
/* 用来描述和父子任务相关的操作历史记录。*/
$lang->action->desc->createchildren = '$date, 由 <strong>$actor</strong> 创建子任务 <strong>$extra</strong>。' . "\n";
@@ -419,6 +423,10 @@ $lang->action->label->switchtolight = '从全生命周期管理模式切
$lang->action->label->linkedrepo = '关联代码库到';
$lang->action->label->unlinkedrepo = '取消了项目与代码库的关联';
$lang->action->label->unlinkproduct = '取消了与产品的关联';
$lang->action->label->createdsnapshot = '创建了快照';
$lang->action->label->restoredsnapshot = '还原了快照';
$lang->action->label->editsnapshot = '编辑了快照';
$lang->action->label->deletesnapshot = '编辑了快照';
/* 动态信息按照对象分组 */
$lang->action->dynamicAction = new stdclass();
+4 -2
View File
@@ -565,8 +565,9 @@ class bug extends control
}
else
{
$builds = $this->loadModel('build')->getBuildPairs($productID, $branch, 'noempty,noterminate,nodone,withbranch,noreleased');
$stories = $this->story->getProductStoryPairs($productID, $branch, 0, 'all','id_desc', 0, 'full', 'story', false);
$moduleID = $moduleID ? $moduleID : 0;
$builds = $this->loadModel('build')->getBuildPairs($productID, $branch, 'noempty,noterminate,nodone,withbranch,noreleased');
$stories = $this->story->getProductStoryPairs($productID, $branch, $moduleID, 'all','id_desc', 0, 'full', 'story', false);
}
$moduleOwner = $this->bug->getModuleOwner($moduleID, $productID);
@@ -665,6 +666,7 @@ class bug extends control
$this->view->storyID = $storyID;
$this->view->buildID = $buildID;
$this->view->caseID = $caseID;
$this->view->resultFiles = (!empty($resultID) and !empty($stepIdList)) ? $this->loadModel('file')->getByObject('stepResult', $resultID, str_replace('_', ',', $stepIdList)) : array();
$this->view->runID = $runID;
$this->view->version = $version;
$this->view->testtask = $testtask;
+19 -7
View File
@@ -78,7 +78,7 @@ class bugModel extends model
->join('mailto', ',')
->join('os', ',')
->join('browser', ',')
->remove('files,labels,uid,oldTaskID,contactListMenu,region,lane,ticket')
->remove('files,labels,uid,oldTaskID,contactListMenu,region,lane,ticket,deleteFiles,resultFiles')
->get();
/* Check repeat bug. */
@@ -98,6 +98,23 @@ class bugModel extends model
{
$bugID = $this->dao->lastInsertID();
if(isset($_POST['resultFiles']))
{
$resultFiles = $_POST['resultFiles'];
if(isset($_POST['deleteFiles']))
{
foreach($_POST['deleteFiles'] as $deletedCaseFileID) $resultFiles = trim(str_replace(",$deletedCaseFileID,", ',', ",$resultFiles,"), ',');
}
$files = $this->dao->select('*')->from(TABLE_FILE)->where('id')->in($resultFiles)->fetchAll('id');
foreach($files as $file)
{
unset($file->id);
$file->objectType = 'bug';
$file->objectID = $bugID;
$this->dao->insert(TABLE_FILE)->data($file)->exec();
}
}
$this->file->updateObjectID($this->post->uid, $bugID, 'bug');
$this->file->saveUpload('bug', $bugID);
empty($bug->case) ? $this->loadModel('score')->create('bug', 'create', $bugID) : $this->loadModel('score')->create('bug', 'createFormCase', $bug->case);
@@ -3728,13 +3745,8 @@ class bugModel extends model
/* Get related objects title or names. */
$table = $this->config->objectTables[$object];
if($table) $relatedObjects = $this->dao->select($pairs)->from($table)->where('id')->in($relatedObjectIdList)->fetchPairs();
if($object == 'branch' and $this->session->currentProductType != 'normal')
{
$productID = current($bugs)->product;
$relatedObjects = $this->dao->select($pairs)->from($table)->where('product')->eq($productID)->fetchPairs();
}
if(in_array($object, array('build','resolvedBuild','branch'))) $relatedObjects = array('trunk' => $this->lang->trunk) + $relatedObjects;
if(in_array($object, array('build','resolvedBuild'))) $relatedObjects = array('trunk' => $this->lang->trunk) + $relatedObjects;
return array('' => '', 0 => '') + $relatedObjects;
}
+10 -1
View File
@@ -335,7 +335,16 @@ if($this->app->tab == 'project') js::set('objectID', $projectID);
<?php $this->printExtendFields('', 'table');?>
<tr>
<th><?php echo $lang->bug->files;?></th>
<td colspan='2'><?php echo $this->fetch('file', 'buildform', 'fileCount=1&percent=0.85');?></td>
<td colspan='2'>
<?php
if($caseID)
{
echo $this->fetch('file', 'printFiles', array('files' => $resultFiles, 'fieldset' => 'false', 'object' => null, 'method' => 'edit', 'showDelete' => true, 'showEdit' => false));
echo html::hidden('resultFiles', implode(',', array_keys($resultFiles)));
}
echo $this->fetch('file', 'buildform', 'fileCount=1&percent=0.85');
?>
</td>
</tr>
</tbody>
<tfoot>
+8 -1
View File
@@ -1676,8 +1676,15 @@ class execution extends control
}
$importPlanStoryTips = $multiBranchProduct ? $this->lang->execution->importBranchPlanStory : $this->lang->execution->importPlanStory;
if(!$execution->hasProduct)
{
return print(js::locate(inlink('create', "projectID=$projectID&executionID=$executionID")));
}
else
{
return print(js::confirm($importPlanStoryTips, inlink('create', "projectID=$projectID&executionID=$executionID&copyExecutionID=&planID=$planID&confirm=yes"), inlink('create', "projectID=$projectID&executionID=$executionID")));
return print(js::confirm($importPlanStoryTips, inlink('create', "projectID=$projectID&executionID=$executionID&copyExecutionID=&planID=$planID&confirm=yes"), inlink('create', "projectID=$projectID&executionID=$executionID")));
}
}
}
+3 -1
View File
@@ -293,16 +293,18 @@ class file extends control
* @param object $object
* @param string $method
* @param bool $showDelete
* @param bool $showEdit
* @access public
* @return void
*/
public function printFiles($files, $fieldset, $object = null, $method = 'view', $showDelete = true)
public function printFiles($files, $fieldset, $object = null, $method = 'view', $showDelete = true, $showEdit = true)
{
$this->view->files = $files;
$this->view->fieldset = $fieldset;
$this->view->object = $object;
$this->view->method = $method;
$this->view->showDelete = $showDelete;
$this->view->showEdit = $showEdit;
if(strpos('view,edit', $method) !== false and $this->app->clientDevice != 'mobile') return $this->display('file', 'viewfiles');
$this->display();
+1 -1
View File
@@ -46,7 +46,7 @@ class fileModel extends model
->where('objectType')->eq($objectType)
->andWhere('objectID')->in($objectID)
->andWhere('extra')->ne('editor')
->beginIF($extra)->andWhere('extra')->eq($extra)
->beginIF($extra)->andWhere('extra')->in($extra)->fi()
->andWhere('deleted')->eq('0')
->orderBy('id')
->fetchAll('id');
+1 -1
View File
@@ -220,7 +220,7 @@ function setFileName(fileID)
common::printLink('file', 'download', "fileID=$file->id", "<i class='icon icon-download'></i>", '_blank', "class='fileAction btn btn-link text-primary' title='{$lang->file->downloadFile}'");
if(common::hasPriv($objectType, 'edit', $object))
{
if(common::hasPriv('file', 'edit')) echo html::a('###', "<i class='icon icon-pencil-alt'></i>", '', "id='renameFile$file->id' class='fileAction btn btn-link edit text-primary' onclick='showRenameBox($file->id)' title='{$lang->file->edit}'");
if($showEdit and common::hasPriv('file', 'edit')) echo html::a('###', "<i class='icon icon-pencil-alt'></i>", '', "id='renameFile$file->id' class='fileAction btn btn-link edit text-primary' onclick='showRenameBox($file->id)' title='{$lang->file->edit}'");
if($showDelete and common::hasPriv('file', 'delete')) echo html::a('###', "<i class='icon icon-trash'></i>", '', "class='fileAction btn btn-link text-primary' onclick='deleteFile($file->id, this)' title='$lang->delete'");
}
echo '</span>';
+22 -12
View File
@@ -1239,18 +1239,23 @@ $lang->zahost->methodOrder[30] = 'downloadImage';
$lang->zahost->methodOrder[35] = 'cancelDownload';
$lang->resource->zanode = new stdclass();
$lang->resource->zanode->browse = 'browse';
$lang->resource->zanode->create = 'create';
$lang->resource->zanode->edit = 'edit';
$lang->resource->zanode->destroy = 'destroy';
$lang->resource->zanode->reboot = 'reboot';
$lang->resource->zanode->suspend = 'suspend';
$lang->resource->zanode->resume = 'resume';
$lang->resource->zanode->getVNC = 'getVNC';
$lang->resource->zanode->start = 'boot';
$lang->resource->zanode->close = 'shutdown';
$lang->resource->zanode->view = 'view';
$lang->resource->zanode->createImage = 'createImage';
$lang->resource->zanode->browse = 'browse';
$lang->resource->zanode->create = 'create';
$lang->resource->zanode->edit = 'edit';
$lang->resource->zanode->destroy = 'destroy';
$lang->resource->zanode->reboot = 'reboot';
$lang->resource->zanode->suspend = 'suspend';
$lang->resource->zanode->resume = 'resume';
$lang->resource->zanode->getVNC = 'getVNC';
$lang->resource->zanode->start = 'boot';
$lang->resource->zanode->close = 'shutdown';
$lang->resource->zanode->view = 'view';
$lang->resource->zanode->createImage = 'createImage';
$lang->resource->zanode->browseSnapshot = 'browseSnapshot';
$lang->resource->zanode->createSnapshot = 'createSnapshot';
$lang->resource->zanode->editSnapshot = 'editSnapshot';
$lang->resource->zanode->restoreSnapshot = 'restoreSnapshot';
$lang->resource->zanode->deleteSnapshot = 'deleteSnapshot';
$lang->zanode->methodOrder[0] = 'browse';
$lang->zanode->methodOrder[5] = 'create';
@@ -1264,6 +1269,11 @@ $lang->zanode->methodOrder[40] = 'start';
$lang->zanode->methodOrder[45] = 'close';
$lang->zanode->methodOrder[50] = 'view';
$lang->zanode->methodOrder[55] = 'createImage';
$lang->zanode->methodOrder[60] = 'browseSnapshot';
$lang->zanode->methodOrder[65] = 'createSnapshot';
$lang->zanode->methodOrder[70] = 'editSnapshot';
$lang->zanode->methodOrder[75] = 'restoreSnapshot';
$lang->zanode->methodOrder[80] = 'deleteSnapshot';
$lang->resource->repo = new stdclass();
$lang->resource->repo->browse = 'browseAction';
+1 -1
View File
@@ -54,7 +54,7 @@
<td><?php echo $queue->createdDate?></td>
<td><?php echo $queue->sendTime?></td>
<td><?php echo zget($lang->mail->statusList, $queue->status)?></td>
<td class='text-left'><?php echo $queue->failReason?></td>
<td class='text-left' title="<?php echo strip_tags($queue->failReason);?>"><?php echo $queue->failReason?></td>
<td class='c-actions'>
<?php
if(common::hasPriv('mail', 'delete')) echo html::a(inlink('delete', "id=$queue->id"), $lang->delete, 'hiddenwin');
+2
View File
@@ -103,6 +103,7 @@ $lang->misc->feature->themeDesc = '<p>ZenTao 15.0+ a new "Youth Blue" theme
$lang->misc->feature->visionsDesc = "<p>The concept of interface has been added since 16.5. Users can deal with R&D affairs in <span style='color: #0c60e1'>[Full Feature Interface]</span> and daily office affairs in <span style='color: #0c60e1'>[Operation Management Interface]</span>.</p><p>You can view the current interface on the avatar, and click the name of the interface to view and switch other interfaces.</p>";
$lang->misc->feature->visionsImage = 'theme/default/images/main/visions_en.png';
$lang->misc->releaseDate['18.1'] = '2023-02-08';
$lang->misc->releaseDate['18.0'] = '2023-01-03';
$lang->misc->releaseDate['18.0.beta3'] = '2022-12-26';
$lang->misc->releaseDate['18.0.beta2'] = '2022-12-14';
@@ -196,6 +197,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['18.1'][] = array('title' => 'The automation testing solution interaction is optimized, while a new snapshot management function is newly added. ZenTao IM implemented online collaboration of PPT documents.Fix bugs.', 'desc' => '');
$lang->misc->feature->all['18.0'][] = array('title' => "Automated test solutions are proposed. Work order related functions are added to the Operation Management Interface. Approval workflow support for adding all types of notifications. And at the same time, we have further improved the earned value calculation rules.", 'desc' => '');
$lang->misc->feature->all['18.0.beta3'][] = array('title' => "The module Statistic is upgraded to BI, with 5 built-in large screens of macro management dimensions.", 'desc' => '');
$lang->misc->feature->all['18.0.beta2'][] = array('title' => "We have optimized the product with multi-branches/multi-platforms. It's supported to create siblings stories. It's possible for Plan, Build, and Release to link requirements or bugs beyond their parent branch. ZenTao Client has implemented the robot chatting mechanism.", 'desc' => '');
+2
View File
@@ -103,6 +103,7 @@ $lang->misc->feature->themeDesc = '<p>ZenTao 15.0+ a new "Youth Blue" theme
$lang->misc->feature->visionsDesc = "<p>The concept of interface has been added since 16.5. Users can deal with R&D affairs in <span style='color: #0c60e1'>[Full Feature Interface]</span> and daily office affairs in <span style='color: #0c60e1'>[Operation Management Interface]</span>.</p><p>You can view the current interface on the avatar, and click the name of the interface to view and switch other interfaces.</p>";
$lang->misc->feature->visionsImage = 'theme/default/images/main/visions_en.png';
$lang->misc->releaseDate['18.1'] = '2023-02-08';
$lang->misc->releaseDate['18.0'] = '2023-01-03';
$lang->misc->releaseDate['18.0.beta3'] = '2022-12-26';
$lang->misc->releaseDate['18.0.beta2'] = '2022-12-14';
@@ -196,6 +197,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['18.1'][] = array('title' => 'The automation testing solution interaction is optimized, while a new snapshot management function is newly added. ZenTao IM implemented online collaboration of PPT documents.Fix bugs.', 'desc' => '');
$lang->misc->feature->all['18.0'][] = array('title' => "Automated test solutions are proposed. Work order related functions are added to the Operation Management Interface. Approval workflow support for adding all types of notifications. And at the same time, we have further improved the earned value calculation rules.", 'desc' => '');
$lang->misc->feature->all['18.0.beta3'][] = array('title' => "The module Statistic is upgraded to BI, with 5 built-in large screens of macro management dimensions.", 'desc' => '');
$lang->misc->feature->all['18.0.beta2'][] = array('title' => "We have optimized the product with multi-branches/multi-platforms. It's supported to create siblings stories. It's possible for Plan, Build, and Release to link requirements or bugs beyond their parent branch. ZenTao Client has implemented the robot chatting mechanism.", 'desc' => '');
+2
View File
@@ -103,6 +103,7 @@ $lang->misc->feature->themeDesc = '<p>ZenTao 15.0+ a new "Youth Blue" theme
$lang->misc->feature->visionsDesc = "<p>The concept of interface has been added since 16.5. Users can deal with R&D affairs in <span style='color: #0c60e1'>[Full Feature Interface]</span> and daily office affairs in <span style='color: #0c60e1'>[Operation Management Interface]</span>.</p><p>You can view the current interface on the avatar, and click the name of the interface to view and switch other interfaces.</p>";
$lang->misc->feature->visionsImage = 'theme/default/images/main/visions_en.png';
$lang->misc->releaseDate['18.1'] = '2023-02-08';
$lang->misc->releaseDate['18.0'] = '2023-01-03';
$lang->misc->releaseDate['18.0.beta3'] = '2022-12-26';
$lang->misc->releaseDate['18.0.beta2'] = '2022-12-14';
@@ -196,6 +197,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['18.1'][] = array('title' => 'The automation testing solution interaction is optimized, while a new snapshot management function is newly added. ZenTao IM implemented online collaboration of PPT documents.Fix bugs.', 'desc' => '');
$lang->misc->feature->all['18.0'][] = array('title' => "Automated test solutions are proposed. Work order related functions are added to the Operation Management Interface. Approval workflow support for adding all types of notifications. And at the same time, we have further improved the earned value calculation rules.", 'desc' => '');
$lang->misc->feature->all['18.0.beta3'][] = array('title' => "The module Statistic is upgraded to BI, with 5 built-in large screens of macro management dimensions.", 'desc' => '');
$lang->misc->feature->all['18.0.beta2'][] = array('title' => "We have optimized the product with multi-branches/multi-platforms. It's supported to create siblings stories. It's possible for Plan, Build, and Release to link requirements or bugs beyond their parent branch. ZenTao Client has implemented the robot chatting mechanism.", 'desc' => '');
+2
View File
@@ -104,6 +104,7 @@ $lang->misc->feature->visionsDesc = "<p>从16.5开始增加了界面概念,
$lang->misc->feature->visionsImage = 'theme/default/images/main/visions.png';
/* Release Date. */
$lang->misc->releaseDate['18.1'] = '2023-02-08';
$lang->misc->releaseDate['18.0'] = '2023-01-03';
$lang->misc->releaseDate['18.0.beta3'] = '2022-12-26';
$lang->misc->releaseDate['18.0.beta2'] = '2022-12-14';
@@ -198,6 +199,7 @@ $lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
/* Release Detail. */
$lang->misc->feature->all['18.1'][] = array('title' => '自动化测试解决方案交互优化、新增快照管理功能。禅道客户端实现了 PPT文档在线协作。修复Bug。', 'desc' => '');
$lang->misc->feature->all['18.0'][] = array('title' => '推出自动化测试解决方案;运营管理界面增加工单功能;审批流支持增加所有类型的通知以及挣值计算规则完善。', 'desc' => '');
$lang->misc->feature->all['18.0.beta3'][] = array('title' => '统计模块升级为BI,内置5张宏观管理维度大屏。', 'desc' => '');
$lang->misc->feature->all['18.0.beta2'][] = array('title' => '优化多分支/多平台产品,支持创建孪生需求,计划、版本、发布支持跨分支关联需求和bug,并且禅道客户端实现了机器人会话机制。', 'desc' => '');
+1
View File
@@ -1016,6 +1016,7 @@ EOF;
$auditplans = $this->auditplan->getList(0, $browseType, $param, $orderBy, $pager);
$this->view->executions = $this->loadModel('execution')->getPairs();
$this->view->projects = $this->loadModel('project')->getPairs();
$this->view->processTypeList = $this->lang->process->classify;
$this->view->processes = $this->pssp->getProcesses();
$this->view->activities = $this->pssp->getActivityPairs();
+8
View File
@@ -1303,14 +1303,22 @@ class productModel extends model
{
$projectList = $this->dao->select('t2.*')->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
->leftJoin(TABLE_TEAM)->alias('t3')->on('t2.id=t3.root')
->leftJoin(TABLE_STAKEHOLDER)->alias('t4')->on('t2.id=t4.objectID')
->where('t1.product')->eq($productID)
->andWhere('t2.type')->eq('project')
->beginIF($this->cookie->involved or $involved)->andWhere('t3.type')->eq('project')->fi()
->beginIF($browseType == 'undone')->andWhere('t2.status')->in('wait,doing')->fi()
->beginIF(strpos(",all,undone,", ",$browseType,") === false)->andWhere('t2.status')->eq($browseType)->fi()
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->projects)->fi()
->beginIF($this->cookie->involved or $involved)
->andWhere('t2.openedBy', true)->eq($this->app->user->account)
->orWhere('t2.PM')->eq($this->app->user->account)
->orWhere('t3.account')->eq($this->app->user->account)
->orWhere('(t4.user')->eq($this->app->user->account)
->andWhere('t4.deleted')->eq(0)
->markRight(1)
->orWhere("CONCAT(',', t2.whitelist, ',')")->like("%,{$this->app->user->account},%")
->markRight(1)
->fi()
->beginIF($branch !== '' and $branch !== 'all')->andWhere('t1.branch')->in($branch)->fi()
+7
View File
@@ -69,6 +69,13 @@ $(function()
infoShowed = true;
}
if(href !== '')
{
type = href == '#stories' ? 'story' : (href == '#bugs' ? 'bug' : 'planInfo');
var viewLink = createLink('productplan', 'view', 'planID=' + planID + '&type=' + type + (typeof(param) == 'undefined' ? '' : param) + (typeof(orderBy) == 'undefined' ? '' : "&orderBy=" + orderBy));
if(type == 'planInfo') viewLink = createLink('productplan', 'view', 'planID=' + planID + '&type=' + type);
self.location.href = viewLink;
}
});
$('#storyList').on('sort.sortable', function(e, data)
+6 -6
View File
@@ -66,7 +66,7 @@
<?php endif;?>
</a>
</li>
<li>
<li class='<?php if($type == 'planInfo') echo 'active'?>'>
<a href='#planInfo' data-toggle='tab'><?php echo html::icon($lang->icons['plan'], 'text-info') . ' ' . $lang->productplan->view;?></a>
</li>
</ul>
@@ -137,17 +137,17 @@
<?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?>
</th>
<?php if($canOrder):?>
<th class='w-70px'><?php common::printOrderLink('order', $orderBy, $vars, $lang->productplan->updateOrder);?></th>
<th class='w-90px'><?php common::printOrderLink('order', $orderBy, $vars, $lang->productplan->updateOrder);?></th>
<?php endif;?>
<th class='text-left'><?php common::printOrderLink('title', $orderBy, $vars, $lang->story->title);?></th>
<th class='w-150px text-left'><?php common::printOrderLink('module', $orderBy, $vars, $lang->story->module);?></th>
<th class='w-90px text-left'><?php common::printOrderLink('module', $orderBy, $vars, $lang->story->module);?></th>
<th class='w-70px' title='<?php echo $lang->pri;?>'><?php common::printOrderLink('pri', $orderBy, $vars, $lang->priAB);?></th>
<th class='w-70px'><?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
<th class='c-user'><?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
<th class='c-user'><?php common::printOrderLink('assignedTo', $orderBy, $vars, $lang->assignedToAB);?></th>
<th class='w-70px text-right'><?php common::printOrderLink('estimate', $orderBy, $vars, $lang->story->estimateAB);?></th>
<th class='w-110px text-right'><?php common::printOrderLink('estimate', $orderBy, $vars, $lang->story->estimateAB);?></th>
<th class='w-80px'><?php common::printOrderLink('stage', $orderBy, $vars, $lang->story->stageAB);?></th>
<th class='c-actions-1'><?php echo $lang->actions?></th>
<th class='c-actions-1 w-90px'><?php echo $lang->actions?></th>
<?php endif;?>
</tr>
</thead>
@@ -533,7 +533,7 @@
<?php endif;?>
</form>
</div>
<div id='planInfo' class='tab-pane'>
<div id='planInfo' class='tab-pane <?php if($type == 'planInfo') echo 'active';?>'>
<div class='cell'>
<div class='detail'>
<div class='detail-title'><?php echo $lang->productplan->basicInfo;?></div>
+3 -1
View File
@@ -615,7 +615,9 @@ class programModel extends model
->andWhere('t1.openedBy', true)->eq($this->app->user->account)
->orWhere('t1.PM')->eq($this->app->user->account)
->orWhere('t2.account')->eq($this->app->user->account)
->orWhere('t3.user')->eq($this->app->user->account)
->orWhere('(t3.user')->eq($this->app->user->account)
->andWhere('t3.deleted')->eq(0)
->markRight(1)
->orWhere("CONCAT(',', t1.whitelist, ',')")->like("%,{$this->app->user->account},%")
->markRight(1)
->fi()
+17 -6
View File
@@ -740,8 +740,6 @@ class programplanModel extends model
$datas[] = $plan;
}
$project = $this->loadModel('project')->getByID($projectID);
$productList = $this->loadModel('product')->getProductPairsByProject($projectID);
$totalPercent = 0;
$totalDevType = 0;
@@ -949,10 +947,6 @@ class programplanModel extends model
$this->setTreePath($stageID);
if($data->acl != 'open') $this->user->updateUserView($stageID, 'sprint');
$linkProducts = $project->division ? array(0 => $productID) : array_keys($productList);
$this->post->set('products', $linkProducts);
$this->execution->updateProducts($stageID);
/* Record version change information. */
$spec = new stdclass();
$spec->project = $stageID;
@@ -974,6 +968,23 @@ class programplanModel extends model
}
}
$linkProducts = array();
$linkBranches = array();
$productList = $this->loadModel('product')->getProducts($projectID);
if($project->division)
{
$linkProducts = array(0 => $productID);
$linkBranches = array(0 => $productList[$productID]->branches);
}
else
{
$linkProducts = array_keys($productList);
foreach($linkProducts as $index => $productID) $linkBranches[$index] = $productList[$productID]->branches;
}
$this->post->set('products', $linkProducts);
$this->post->set('branch', $linkBranches);
$this->execution->updateProducts($stageID);
/* If child plans has milestone, update parent plan set milestone eq 0 . */
if($parentID and $milestone) $this->dao->update(TABLE_PROJECT)->set('milestone')->eq(0)->where('id')->eq($parentID)->exec();
+1 -1
View File
@@ -107,8 +107,8 @@ form {display: block; margin-top: 0em; margin-block-end: 1em;}
</div>
<div class="pull-right btn-toolbar flax">
<div class="btn-group">
<?php echo html::a($this->createLink('project', 'execution', "status=all&projectID=$projectID"),"<i class='icon-list'></i> &nbsp;", '', "class='btn btn-icon switchBtn' title='{$lang->project->bylist}'");?>
<?php echo html::a('',"<i class='icon-gantt-alt'></i> &nbsp;", '', "class='btn btn-icon text-primary switchBtn' title='{$lang->programplan->gantt}'");?>
<?php echo html::a($this->createLink('project', 'execution', "status=all&projectID=$projectID"),"<i class='icon-list'></i> &nbsp;", '', "class='btn btn-icon switchBtn' title='{$lang->project->bylist}'");?>
</div>
<a href='javascript:fullScreen();' id='fullScreenBtn' class='btn btn-link'><i class='icon icon-fullscreen'></i> <?php echo $lang->programplan->full;?></a>
<div class='button-group'>
+1 -1
View File
@@ -45,8 +45,8 @@
<div class='btn-toolbar pull-right'>
<?php if($project->model == 'waterfall' and $this->config->edition == 'max'):?>
<div class="btn-group">
<?php echo html::a('', "<i class='icon-list'></i> &nbsp;", '', "class='btn btn-icon text-primary switchBtn' title='{$lang->project->bylist}'");?>
<?php echo html::a($this->createLink('programplan', 'browse', "projectID=$projectID&productID=$productID&type=gantt"), "<i class='icon-gantt-alt'></i> &nbsp;", '', "class='btn btn-icon switchBtn' title='{$lang->programplan->gantt}'");?>
<?php echo html::a('', "<i class='icon-list'></i> &nbsp;", '', "class='btn btn-icon text-primary switchBtn' title='{$lang->project->bylist}'");?>
</div>
<?php endif;?>
<?php common::printLink('execution', 'export', "status=$status&productID=$productID&orderBy=$orderBy&from=project", "<i class='icon-export muted'> </i> " . $lang->export, '', "class='btn btn-link export'")?>
+24 -3
View File
@@ -10,9 +10,9 @@ function showLink(releaseID, type, param)
/**
* Load URL.
*
* @param string $url
* @param string$type
*
* @param string $url
* @param string$type
* @access public
* @return void
*/
@@ -68,5 +68,26 @@ $(function()
infoShowed = true;
}
if(href !== '')
{
switch(href)
{
case '#stories':
type = 'story';
break;
case '#bugs':
type = 'bug';
break;
case '#leftBugs':
type = 'leftBug';
break;
case '#releaseInfo':
type = 'releaseInfo';
break;
}
var viewLink = createLink('release', 'view', 'releaseID=' + releaseID + '&type=' + type + '&link=' + link + (typeof(param) == 'undefined' ? '' : param) + (typeof(orderBy) == 'undefined' ? '' : "&orderBy=" + orderBy));
if(type == 'releaseInfo') viewLink = createLink('release', 'view', 'releaseID=' + releaseID + '&type=' + type);
self.location.href = viewLink;
}
});
})
+14 -1
View File
@@ -1143,6 +1143,7 @@ class story extends control
/* Append module when change product type. */
$moduleList = array(0 => '/');
$productStoryList = array();
$storyPlans = array();
foreach($stories as $story)
{
if(isset($modules[$story->product][$story->branch]))
@@ -1160,6 +1161,18 @@ class story extends control
$branch = $storyProduct->type == 'branch' ? ($story->branch > 0 ? $story->branch : '0') : 'all';
if(!isset($productStoryList[$story->product][$story->branch])) $productStoryList[$story->product][$story->branch] = $this->story->getProductStoryPairs($story->product, $branch, 0, 'all', 'id_desc', 0, '', $story->type);
}
if(isset($plans[$story->product][$story->branch]) and zget($plans[$story->product][$story->branch], $story->plan))
{
$storyPlans = $plans[$story->product][$story->branch];
$planInfo = $this->dao->select('id,title,begin,end')->from(TABLE_PRODUCTPLAN)->where('id')->eq($story->plan)->fetchAll('id');
$storyPlans[$story->plan] = $planInfo[$story->plan]->title . ' [' . $planInfo[$story->plan]->begin . '~' . $planInfo[$story->plan]->end . ']';
}
else
{
$storyPlans = $plans;
}
}
$this->view->title = $this->lang->story->batchEdit;
@@ -1173,7 +1186,7 @@ class story extends control
$this->view->branchProduct = $branchProduct;
$this->view->storyIdList = $storyIdList;
$this->view->branch = $branch;
$this->view->plans = array('' => '') + $plans;
$this->view->plans = array('' => '') + $storyPlans;
$this->view->storyType = $storyType;
$this->view->stories = $stories;
$this->view->executionID = $executionID;
-1
View File
@@ -25,7 +25,6 @@
.popover.bottom .arrow{border-bottom-color:#ffffff;}
.popover-icon {float:left;}
.popover .content {margin-left:25px;overflow: overlay;}
.hide {display:none !important;}
.twins > a.viewlink {padding:6px;white-space: nowrap;overflow: hidden;display: inline-flex;max-width: 70%;}
.twins > span {max-width: 60px;white-space: nowrap;overflow: hidden;}
.tooltip-inner {max-width: 500px;}
+5
View File
@@ -3022,6 +3022,11 @@ class storyModel extends model
*/
public function getProductStoryPairs($productID = 0, $branch = 'all', $moduleIdList = 0, $status = 'all', $order = 'id_desc', $limit = 0, $type = 'full', $storyType = 'story', $hasParent = true)
{
if($moduleIdList)
{
$moduleInfo = $this->loadModel('tree')->getByID($moduleIdList);
$moduleIdList = $moduleInfo->type == 'bug' ? 0 : $moduleIdList;
}
$stories = $this->dao->select('t1.id, t1.title, t1.module, t1.pri, t1.estimate, t2.name AS product')
->from(TABLE_STORY)->alias('t1')->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id')
->where('1=1')
+1 -1
View File
@@ -85,7 +85,7 @@ foreach(explode(',', $showFields) as $field)
<?php if(!$hiddenPlan):?>
<td class='text-left<?php echo zget($visibleFields, 'plan', ' hidden')?>'>
<?php $planDisabled = $story->parent < 0 ? "disabled='disabled'" : '';?>
<?php echo html::select("plans[$storyID]", isset($plans[$story->product][$story->branch]) ? array('' => '') + $plans[$story->product][$story->branch] : '', $story->plan, "class='form-control picker-select' data-drop-width='auto' $planDisabled");?>
<?php echo html::select("plans[$storyID]", isset($plans) ? array('' => '') + $plans : '', $story->plan, "class='form-control picker-select' data-drop-width='auto' $planDisabled");?>
</td>
<?php endif;?>
<td title='<?php echo $story->title?>'>
+2
View File
@@ -37,6 +37,7 @@ $config->testcase->excludeCheckFileds = ',pri,type,stage,needReview,story,branch
global $lang;
$config->testcase->search['module'] = 'testcase';
$config->testcase->search['fields']['title'] = $lang->testcase->title;
$config->testcase->search['fields']['story'] = $lang->testcase->linkStory;
$config->testcase->search['fields']['id'] = $lang->testcase->id;
$config->testcase->search['fields']['keywords'] = $lang->testcase->keywords;
$config->testcase->search['fields']['lastEditedBy'] = $lang->testcase->lastEditedByAB;
@@ -58,6 +59,7 @@ $config->testcase->search['fields']['openedDate'] = $lang->testcase->openedD
$config->testcase->search['fields']['lastEditedDate'] = $lang->testcase->lastEditedDateAB;
$config->testcase->search['params']['title'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
$config->testcase->search['params']['story'] = array('operator' => 'include', 'control' => 'select', 'values' => '');
$config->testcase->search['params']['module'] = array('operator' => 'belong', 'control' => 'select', 'values' => 'modules');
$config->testcase->search['params']['keywords'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
$config->testcase->search['params']['lastEditedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
+1
View File
@@ -13,6 +13,7 @@ $lang->testcase->id = 'ID';
$lang->testcase->product = $lang->productCommon;
$lang->testcase->project = 'Project';
$lang->testcase->execution = 'Execution';
$lang->testcase->linkStory = 'linkStory';
$lang->testcase->module = 'Module';
$lang->testcase->auto = 'Test Automation Cases';
$lang->testcase->frame = 'Test Automation Cramework';
+1
View File
@@ -13,6 +13,7 @@ $lang->testcase->id = 'ID';
$lang->testcase->product = $lang->productCommon;
$lang->testcase->project = 'Project';
$lang->testcase->execution = 'Execution';
$lang->testcase->linkStory = 'linkStory';
$lang->testcase->module = 'Module';
$lang->testcase->auto = 'Test Automation Cases';
$lang->testcase->frame = 'Test Automation Cramework';
+1
View File
@@ -13,6 +13,7 @@ $lang->testcase->id = 'ID';
$lang->testcase->product = $lang->productCommon;
$lang->testcase->project = 'Project';
$lang->testcase->execution = 'Execution';
$lang->testcase->linkStory = 'linkStory';
$lang->testcase->module = 'Module';
$lang->testcase->auto = 'Test Automation Cases';
$lang->testcase->frame = 'Test Automation Cramework';
+1
View File
@@ -13,6 +13,7 @@ $lang->testcase->id = '用例编号';
$lang->testcase->product = "所属{$lang->productCommon}";
$lang->testcase->project = '所属项目';
$lang->testcase->execution = '所属执行';
$lang->testcase->linkStory = '关联需求';
$lang->testcase->module = '所属模块';
$lang->testcase->auto = '自动化测试用例';
$lang->testcase->frame = '自动化测试框架';
+19
View File
@@ -1059,6 +1059,11 @@ class testtask extends control
* Link cases to a test task.
*
* @param int $taskID
* @param string $type
* @param int $param
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
@@ -1107,7 +1112,21 @@ class testtask extends control
$this->config->testcase->search['actionURL'] = inlink('linkcase', "taskID=$taskID&type=$type&param=$param");
$this->config->testcase->search['style'] = 'simple';
$build = $this->loadModel('build')->getByID($task->build);
$stories = array();
if($build)
{
$stories = $this->dao->select('id,title')->from(TABLE_STORY)->where('id')->in($build->stories)->fetchPairs();
$this->config->testcase->search['params']['story']['values'] = $stories;
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story');
}
if($product->shadow) unset($this->config->testcase->search['fields']['product']);
if($type != 'bystory')
{
unset($this->config->testcase->search['fields']['story']);
unset($this->config->testcase->search['params']['story']);
}
if($task->productType == 'normal')
{
unset($this->config->testcase->search['fields']['branch']);
+11 -9
View File
@@ -399,18 +399,20 @@ class testtaskModel extends model
{
$stories = $this->dao->select('stories')->from(TABLE_BUILD)->where('id')->eq($task->build)->fetch('stories');
$cases = array();
$query = preg_replace('/`(\w+)`/', 't1.`$1`', $query);
if($stories)
{
$cases = $this->dao->select('*')->from(TABLE_CASE)
$cases = $this->dao->select('t1.*,t2.title as storyTitle')->from(TABLE_CASE)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
->where($query)
->beginIF($this->lang->navGroup->testtask != 'qa')->andWhere('project')->eq($this->session->project)->fi()
->andWhere('product')->eq($productID)
->andWhere('status')->ne('wait')
->beginIF($linkedCases)->andWhere('id')->notIN($linkedCases)->fi()
->beginIF($task->branch !== '')->andWhere('branch')->in("0,$task->branch")->fi()
->andWhere('story')->in(trim($stories, ','))
->andWhere('deleted')->eq(0)
->orderBy('id desc')
->beginIF($this->lang->navGroup->testtask != 'qa')->andWhere('t1.project')->eq($this->session->project)->fi()
->andWhere('t1.product')->eq($productID)
->andWhere('t1.status')->ne('wait')
->beginIF($linkedCases)->andWhere('t1.id')->notIN($linkedCases)->fi()
->beginIF($task->branch !== '')->andWhere('t1.branch')->in("0,$task->branch")->fi()
->andWhere('t1.story')->in(trim($stories, ','))
->andWhere('t1.deleted')->eq(0)
->orderBy('t1.id desc')
->page($pager)
->fetchAll();
}
+2
View File
@@ -86,6 +86,7 @@
<th class='c-version text-center'><nobr><?php echo $lang->testtask->linkVersion;?></nobr></th>
<th class='c-pri' title='<?php echo $lang->pri;?>'><?php echo $lang->priAB;?></th>
<th><?php echo $lang->testcase->title;?></th>
<th class="<?php echo $type == 'bystory' ? '' : 'hidden';?>"><?php echo $lang->testcase->linkStory;?></th>
<th class='c-type'><?php echo $lang->testcase->type;?></th>
<th class='c-user'><?php echo $lang->openedByAB;?></th>
<th class='c-user'><?php echo $lang->testtask->lastRunAccount;?></th>
@@ -112,6 +113,7 @@
echo ')';
?>
</td>
<td class="text-left title <?php echo $type == 'bystory' ? '' : 'hidden';?>" title='<?php echo $case->storyTitle?>'><?php if($case->story and $case->storyTitle) echo html::a(helper ::createLink('story', 'view', "storyID=$case->story"), $case->storyTitle);?></td>
<td><?php echo $lang->testcase->typeList[$case->type];?></td>
<td><?php echo zget($users, $case->openedBy);?></td>
<td><?php echo zget($users, $case->lastRunner);?></td>
+1 -1
View File
@@ -152,7 +152,7 @@ class transfer extends control
$this->loadModel($model);
$importFields = !empty($_SESSION[$model . 'TemplateFields']) ? $_SESSION[$model . 'TemplateFields'] : $this->config->$model->templateFields;
if($model == 'testcase' and !empty($_SESSION[$model . 'TemplateFields'])) $this->config->$model->templateFields = implode(',', $importFields);
if($model == 'testcase' and !empty($_SESSION[$model . 'TemplateFields']) and is_array($importFields)) $this->config->$model->templateFields = implode(',', $importFields);
$fields = $this->transfer->initFieldList($model, $importFields, false);
$formatDatas = $this->transfer->format($model, $filter);
$datas = $this->transfer->getPageDatas($formatDatas, $pagerID);
+4 -2
View File
@@ -31,7 +31,8 @@ $config->upgrade->maxVersion['max3_8'] = '17_8';
$config->upgrade->maxVersion['max4_0_beta1'] = '18_0_beta1';
$config->upgrade->maxVersion['max4_0_beta2'] = '18_0_beta2';
$config->upgrade->maxVersion['max4_0_beta3'] = '18_0_beta3';
$config->upgrade->maxVersion['max4_0'] = '18_0'; // max insert position.
$config->upgrade->maxVersion['max4_0'] = '18_0';
$config->upgrade->maxVersion['max4_1'] = '18_1'; // max insert position.
$config->upgrade->bizVersion = array();
$config->upgrade->bizVersion['biz1_0'] = '9_5_1';
@@ -101,7 +102,8 @@ $config->upgrade->bizVersion['biz7_8'] = '17_8';
$config->upgrade->bizVersion['biz8_0_beta1'] = '18_0_beta1';
$config->upgrade->bizVersion['biz8_0_beta2'] = '18_0_beta2';
$config->upgrade->bizVersion['biz8_0_beta3'] = '18_0_beta3';
$config->upgrade->bizVersion['biz8_0'] = '18_0'; // biz insert position.
$config->upgrade->bizVersion['biz8_0'] = '18_0';
$config->upgrade->bizVersion['biz8_1'] = '18_1'; // biz insert position.
$config->upgrade->proVersion = array();
$config->upgrade->proVersion['pro1_0'] = '3_1';
+6 -3
View File
@@ -172,7 +172,8 @@ $lang->upgrade->fromVersions['17_8'] = '17.8';
$lang->upgrade->fromVersions['18_0_beta1'] = '18.0.beta1';
$lang->upgrade->fromVersions['18_0_beta2'] = '18.0.beta2';
$lang->upgrade->fromVersions['18_0_beta3'] = '18.0.beta3';
$lang->upgrade->fromVersions['18_0'] = '18.0'; // pms insert position.
$lang->upgrade->fromVersions['18_0'] = '18.0';
$lang->upgrade->fromVersions['18_1'] = '18.1'; // pms insert position.
global $config;
/* Lite. */
@@ -349,7 +350,8 @@ $lang->upgrade->fromVersions['biz7_8'] = 'Biz7.8';
$lang->upgrade->fromVersions['biz8_0_beta1'] = 'Biz8.0.beta1';
$lang->upgrade->fromVersions['biz8_0_beta2'] = 'Biz8.0.beta2';
$lang->upgrade->fromVersions['biz8_0_beta3'] = 'Biz8.0.beta3';
$lang->upgrade->fromVersions['biz8_0'] = 'Biz8.0'; // biz insert position.
$lang->upgrade->fromVersions['biz8_0'] = 'Biz8.0';
$lang->upgrade->fromVersions['biz8_1'] = 'Biz8.1'; // biz insert position.
/* Max. */
$lang->upgrade->fromVersions['max2_0_beta4'] = 'Max2.0.beta4';
@@ -382,4 +384,5 @@ $lang->upgrade->fromVersions['max3_7'] = 'Max3.7';
$lang->upgrade->fromVersions['max3_8'] = 'Max3.8';
$lang->upgrade->fromVersions['max4_0_beta1'] = 'Max4.0.beta1';
$lang->upgrade->fromVersions['max4_0_beta2'] = 'Max4.0.beta2';
$lang->upgrade->fromVersions['max4_0_beta3'] = 'Max4.0.beta3'; // max insert position.
$lang->upgrade->fromVersions['max4_0_beta3'] = 'Max4.0.beta3';
$lang->upgrade->fromVersions['max4_0'] = 'Max4.0'; // max insert position.
+4 -1
View File
@@ -1080,7 +1080,9 @@ class upgradeModel extends model
case '18_0_beta2':
$confirmContent .= file_get_contents($this->getUpgradeFile('18.0.beta2'));
case '18_0_beta3':
$confirmContent .= file_get_contents($this->getUpgradeFile('18.0.beta3')); // confirm insert position.
$confirmContent .= file_get_contents($this->getUpgradeFile('18.0.beta3'));
case '18_0':
$confirmContent .= file_get_contents($this->getUpgradeFile('18.0')); // confirm insert position.
}
return $confirmContent;
@@ -7558,6 +7560,7 @@ class upgradeModel extends model
{
$project = new stdclass();
$project->name = $sprint->name;
$project->desc = $sprint->desc;
$project->type = 'project';
$project->model = 'scrum';
$project->parent = $programID;
+8 -3
View File
@@ -43,8 +43,13 @@ class zahost extends control
$this->loadModel('search')->setSearchParams($this->config->zahost->search);
$showFeature = false;
$skipAutomation = !empty($this->config->global->skipAutomation) ? $this->config->global->skipAutomation : '';
if(strpos(",$skipAutomation,", $this->app->user->account) === false) $showFeature = true;
$accounts = !empty($this->config->global->skipAutomation) ? $this->config->global->skipAutomation : '';
if(strpos(",$accounts,", $this->app->user->account) === false)
{
$showFeature = true;
$accounts .= ',' . $this->app->user->account;
$this->loadModel('setting')->setItem('system.common.global.skipAutomation', $accounts);
}
$this->view->title = $this->lang->zahost->common;
$this->view->hostList = $hostList;
@@ -164,7 +169,7 @@ class zahost extends control
}
$this->dao->update(TABLE_ZAHOST)->set('deleted')->eq(1)->where('id')->eq($hostID)->exec();
$this->loadModel('action')->create('zahost', $hostID, 'deleted');
$this->loadModel('action')->create('zahost', $hostID, 'deleted', '', $extra = ACTIONMODEL::CAN_UNDELETED);
/* if ajax request, send result. */
if($this->server->ajax)
+1
View File
@@ -20,3 +20,4 @@
.btn-info {background-color: unset;}
.icon-refresh {font-size: 15px;}
.load-indicator:after {top: 33%;}
.btn.disabled i {color: #fff;}
-1
View File
@@ -76,7 +76,6 @@ function setIframeHeight(iframe)
{
var height = iframeWin.document.documentElement.scrollHeight || iframeWin.document.body.scrollHeight
iframe.height = height+10;
console.log(1111, iframe.height)
}
}
}
+4 -1
View File
@@ -85,7 +85,10 @@ class zahostModel extends model
$this->dao->update(TABLE_ZAHOST)->data($hostInfo)
->batchCheck($this->config->zahost->create->requiredFields, 'notempty')
->batchCheck('diskSize,memory', 'float');
->batchCheck('diskSize,memory', 'float')
->check('name', 'unique', "id != $hostID and type in ('vhost', 'zahost')")
->autoCheck();
if(dao::isError()) return false;
$ping = $this->checkAddress($hostInfo->extranet);
+8 -26
View File
@@ -131,43 +131,25 @@
<div class="detail-title"><?php echo $lang->zahost->desc;?></div>
<div class="detail-content article-content"><?php echo !empty($zahost->desc) ? htmlspecialchars_decode($zahost->desc) : $lang->noData;?></div>
</div>
<?php if(!empty($nodeList)): ?>
</div>
<?php if(commonModel::hasPriv('zanode', 'browse')):?>
<div class="cell">
<div class="detail">
<div class="detail-title"><?php echo $lang->zahost->browseNode;?></div>
<?php if(!empty($nodeList)): ?>
<div class="detail-content article-content">
<?php echo "<iframe width='100%' id='nodesIframe' src='" . $this->createLink('zanode', 'list', "hostID=$zahost->id", '', true) . "' frameborder='no' allowfullscreen='true' mozallowfullscreen='true' webkitallowfullscreen='true' allowtransparency='true' scrolling='auto' onload='setIframeHeight(this)' style='min-height:300px;'></iframe>";?>
<!-- <table class='table has-sort-head table-fixed' id='nodeList'>
<thead>
<tr>
<th class='c-name'><?php common::printOrderLink('name', $orderBy, $vars, $lang->zahost->name);?></th>
<th class='c-cpu'><?php common::printOrderLink('cpuCores', $orderBy, $vars, $lang->zanode->cpuCores);?></th>
<th class='c-number'><?php common::printOrderLink('memory', $orderBy, $vars, $lang->zanode->memory);?></th>
<th class='c-number'><?php common::printOrderLink('diskSize', $orderBy, $vars, $lang->zanode->diskSize);?></th>
<th class='c-os'><?php common::printOrderLink('osName', $orderBy, $vars, $lang->zanode->osName);?></th>
<th class='c-status'><?php common::printOrderLink('status', $orderBy, $vars, $lang->zanode->status);?></th>
</tr>
</thead>
<tbody>
<?php foreach($nodeList as $node):?>
<tr>
<td title="<?php echo $node->name;?>"><?php echo html::a($this->createLink('zanode', 'view', "id=$node->id"), $node->name, '_target', "");?></td>
<td><?php echo zget($config->zanode->os->cpuCores, $node->cpuCores);?></td>
<td><?php echo $node->memory . $this->lang->zahost->unitList['GB'];?></td>
<td><?php echo $node->diskSize . $this->lang->zahost->unitList['GB'];?></td>
<td><?php echo $node->osName;?></td>
<td><?php echo zget($lang->zanode->statusList, $node->status);?></td>
</tr>
<?php endforeach;?>
</tbody>
</table> -->
</div>
<?php else: ?>
<div class="detail-content article-content"><?php echo $lang->noData;?></div>
<?php endif; ?>
</div>
<?php endif; ?>
<?php
$canBeChanged = common::canBeChanged('zahost', $zahost);
if($canBeChanged) $actionFormLink = $this->createLink('action', 'comment', "objectType=zahost&objectID=$zahost->hostID");
?>
</div>
<?php endif; ?>
<?php $this->printExtendFields($zahost, 'div', "position=left&inForm=0&inCell=1");?>
<div class='main-actions'>
<div class="btn-toolbar">
+156 -2
View File
@@ -44,8 +44,13 @@ class zanode extends control
$this->loadModel('search')->setSearchParams($this->config->zanode->search);
$showFeature = false;
$skipAutomation = !empty($this->config->global->skipAutomation) ? $this->config->global->skipAutomation : '';
if(strpos(",$skipAutomation,", $this->app->user->account) === false) $showFeature = true;
$accounts = !empty($this->config->global->skipAutomation) ? $this->config->global->skipAutomation : '';
if(strpos(",$accounts,", $this->app->user->account) === false)
{
$showFeature = true;
$accounts .= ',' . $this->app->user->account;
$this->loadModel('setting')->setItem('system.common.global.skipAutomation', $accounts);
}
$this->view->title = $this->lang->zanode->common;
$this->view->users = $this->loadModel('user')->getPairs('noletter|nodeleted');
@@ -73,6 +78,10 @@ class zanode extends control
*/
public function list($hostID, $orderBy = 'id_desc')
{
if(!commonModel::hasPriv('zanode', 'browse'))
{
$this->loadModel('common')->deny('zanode', 'browse');
}
$this->view->title = $this->lang->zanode->common;
$this->view->nodeList = $this->loadModel("zanode")->getListByHost($hostID, $orderBy);
$this->view->orderBy = $orderBy;
@@ -155,6 +164,7 @@ class zanode extends control
$this->view->token = !empty($vnc->token) ? $vnc->token:'';
$this->view->title = $this->lang->zanode->view;
$this->view->zanode = $node;
$this->view->snapshotList = $this->zanode->getSnapshotList($id);
$this->view->actions = $this->loadModel('action')->getList('zanode', $id);
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->display();
@@ -276,6 +286,90 @@ class zanode extends control
$this->display();
}
/**
* Create snapshot.
*
* @param int $zanodeID
* @access public
* @return void
*/
public function createSnapshot($nodeID = 0)
{
$node = $this->zanode->getNodeByID($nodeID);
if($_POST)
{
$this->zanode->createSnapshot($nodeID);
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
return $this->send($response);
}
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->node = $node;
$this->display();
}
/**
* Edit Snapshot.
*
* @param int $snapshotID
* @access public
* @return void
*/
public function editSnapshot($snapshotID)
{
$snapshot = $this->zanode->getImageByID($snapshotID);
if($_POST)
{
$this->zanode->editSnapshot($snapshotID);
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
return $this->send($response);
}
$this->loadModel('action')->create('zanode', $snapshot->host, 'editSnapshot', '', $snapshot->localName ? $snapshot->localName : $snapshot->name);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->snapshot = $snapshot;
$this->display();
}
/**
* Delete Snapshot.
*
* @param int $snapshotID
* @param string $confirm
* @access public
* @return void
*/
public function deleteSnapshot($snapshotID, $confirm = 'no')
{
if($confirm == 'no')
{
return print(js::confirm($this->lang->zanode->confirmDeleteSnapshot, inlink('deleteSnapshot', "snapshotID={$snapshotID}&confirm=yes")));
}
$result = $this->zanode->deleteSnapshot($snapshotID);
if($result !== true)
{
return print(js::alert($result));
}
else
{
if(isonlybody()) return print(js::alert($this->lang->zanode->actionSuccess) . js::reload('parent.parent'));
return print(js::alert($this->lang->zanode->actionSuccess) . js::locate($this->createLink('zanode', 'browse'), 'parent'));
}
}
/**
* Desctroy node.
*
@@ -324,6 +418,66 @@ class zanode extends control
$this->display();
}
/**
* Browse snapshot.
*
* @param int $nodeID
* @param string $browseType
* @param int $param
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function browseSnapshot($nodeID, $browseType = 'all', $param = 0, $orderBy = 'id', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->app->loadLang('zahost');
$this->app->loadClass('pager', $static = true);
$pager = pager::init($recTotal, $recPerPage, $pageID);
$snapshotList = $this->zanode->getSnapshotList($nodeID, $browseType, $param, $orderBy, $pager);
$this->view->title = $this->lang->zanode->browseSnapshot;
$this->view->nodeID = $nodeID;
$this->view->node = $this->zanode->getNodeByID($nodeID);
$this->view->snapshotList = $snapshotList;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->pager = $pager;
$this->view->param = $param;
$this->view->orderBy = $orderBy;
$this->view->browseType = $browseType;
$this->display();
}
/**
* Restore node.
*
* @param int $nodeID
* @return void
*/
public function restoreSnapshot($nodeID, $snapshotID, $confirm = 'no')
{
if($confirm == 'no')
{
return print(js::confirm($this->lang->zanode->confirmRestore, inlink('restoreSnapshot', "nodeID={$nodeID}&snapshotID={$snapshotID}&confirm=yes")));
}
$this->zanode->restoreSnapshot($nodeID, $snapshotID);
if(dao::isError())
{
return print(js::alert(dao::getError()) . js::reload('parent'));
}
else
{
if(isonlybody()) return print(js::alert($this->lang->zanode->actionSuccess) . js::reload('parent.parent'));
return print(js::alert($this->lang->zanode->actionSuccess) . js::locate($this->createLink('zanode', 'browse'), 'parent'));
}
}
/**
* Ajax get template pairs by api.
*
+6
View File
@@ -0,0 +1,6 @@
#main{min-width: 0!important;padding:0!important;}
body{background-color: #fff!important;}
.c-createdBy {width: 100px;}
.c-datetime {width: 130px;}
.c-status {width: 120px;}
+1
View File
@@ -16,3 +16,4 @@
.checkStatus{color: #313c52;}
.node-not-wrap{white-space: nowrap;}
.btn-info {background-color: unset;}
.btn.disabled i {color: #fff;}
+7
View File
@@ -0,0 +1,7 @@
$(function()
{
var myPager = $('.pager').data('zui.pager');
myPager.options.menuDirection = 'dropdown';
myPager.set();
});
+37
View File
@@ -160,6 +160,31 @@ $('.btn-pwd-copy').live('click', function()
}, 2000)
})
$('.btn-pwd-show').live('click', function()
{
var pwd = $('#pwd-copy').text();
var pwdStar = "******".padEnd(pwd.length, '*')
var html = $(this).html()
if(html.indexOf('icon-eye-off') != -1)
{
$('#pwd-text').text(pwdStar)
$(this).html("<i class='icon-common-eye icon-eye' title='" + zanodeLang.showPwd + "'></i>")
}
else
{
$('#pwd-text').text(pwd)
$(this).html("<i class='icon-common-eye icon-eye-off' title='" + zanodeLang.hidePwd + "'></i>")
}
})
$('#jumpManual').click(function()
{
var encodedHelpPageUrl = encodeURIComponent('https://www.zentao.net/book/zentaopms/974.html?fullScreen=zentao');
var urlForNewTab = window.location.origin + '#app=help&url=' + encodedHelpPageUrl;
window.open(urlForNewTab)
})
$(function(){
checkServiceStatus();
checkInterval = setInterval(() => {
@@ -171,3 +196,15 @@ $(function(){
checkServiceStatus();
}, 2000);
})
/**
* Edit Snapshot.
*
* @param string $link
* @access public
* @return void
*/
function editSnapshot(link)
{
$('#editSnapshot').attr('href', link).click();
}
+19
View File
@@ -59,6 +59,8 @@ $lang->zanode->copy = 'Click to copy';
$lang->zanode->copied = 'Copy successful';
$lang->zanode->manual = 'Manual';
$lang->zanode->initializing = 'Initializing';
$lang->zanode->showPwd = 'Show Password';
$lang->zanode->hidePwd = 'Hide Password';
$lang->automation = new stdClass();
$lang->automation->scriptPath = $lang->zanode->scriptPath;
@@ -79,6 +81,22 @@ $lang->zanode->createImageSuccess = 'Successed, You can use this image to create
$lang->zanode->createImageFail = 'Failed to create';
$lang->zanode->createImageButton = 'Create image';
$lang->zanode->snapshotName = 'Snapshot Name';
$lang->zanode->browseSnapshot = 'Snapshot List';
$lang->zanode->createSnapshot = 'Create Snapshot';
$lang->zanode->editSnapshot = 'Edit Snapshot';
$lang->zanode->restoreSnapshot = 'Revert Snapshot';
$lang->zanode->deleteSnapshot = 'Delete Snapshot';
$lang->zanode->snapshotEmpty = 'No snapshots';
$lang->zanode->confirmDeleteSnapshot = "The snapshot cannot be restored from the recycle bin after being deleted. Are you sure to continue?";
$lang->zanode->snapshot->statusList['creating'] = 'Creating';
$lang->zanode->snapshot->statusList['completed'] = 'Create Completed';
$lang->zanode->snapshot->statusList['failed'] = 'Create Failed';
$lang->zanode->snapshot->statusList['restoring'] = 'Restoring';
$lang->zanode->snapshot->statusList['restore_failed'] = 'Restore Failed';
$lang->zanode->snapshot->statusList['restore_completed'] = 'Restore Completed';
$lang->zanode->imageNameEmpty = 'Name can not be empty.';
$lang->zanode->runTimeout = 'Network connection timeout, please check the host and execution node status.';
@@ -101,6 +119,7 @@ $lang->zanode->statusList['shutodown'] = 'shutdown';
$lang->zanode->statusList['destroy_fail'] = 'Destroy Fail';
$lang->zanode->statusList['wait'] = 'Initializing';
$lang->zanode->statusList['online'] = 'Online';
$lang->zanode->statusList['restoring'] = 'Restoring';
$lang->zanode->initNotice = "Succeeded. Please initialize the execution node or return to the list.";
$lang->zanode->initButton = "Initialize";
+30 -7
View File
@@ -42,12 +42,14 @@ $lang->zanode->vnc = 'VNC Port';
$lang->zanode->destroyAt = 'Destroy Time';
$lang->zanode->creater = 'Creator';
$lang->zanode->createdDate = 'Create Date';
$lang->zanode->confirmDelete = "Are you sure about destroying the ZenAgent Node?";
$lang->zanode->confirmBoot = "Are you sure to start the ZenAgent Node?";
$lang->zanode->confirmReboot = "Are you sure to restart the ZenAgent Node?";
$lang->zanode->confirmShutdown = "Are you sure to shutdown the ZenAgent Node?";
$lang->zanode->confirmSuspend = "Are you sure to suspend the ZenAgent Node?";
$lang->zanode->confirmResume = "Are you sure to resume the ZenAgent Node?";
$lang->zanode->confirmDelete = "Are you sure about destroying the ZenAgent Node?";
$lang->zanode->confirmBoot = "Are you sure to start the ZenAgent Node?";
$lang->zanode->confirmReboot = "Are you sure to restart the ZenAgent Node?";
$lang->zanode->confirmShutdown = "Are you sure to shutdown the ZenAgent Node?";
$lang->zanode->confirmSuspend = "Are you sure to suspend the ZenAgent Node?";
$lang->zanode->confirmResume = "Are you sure to resume the ZenAgent Node?";
$lang->zanode->confirmRestore = "Are you sure to restore the ZenAgent Node?";
$lang->zanode->confirmRestore = "The ZenAgent Node will be restored to this snapshot state, are you sure you want to continue?";
$lang->zanode->actionSuccess = 'Success';
$lang->zanode->deleted = "Deleted";
$lang->zanode->scriptPath = "Script path";
@@ -59,6 +61,8 @@ $lang->zanode->copy = 'Click to copy';
$lang->zanode->copied = 'Copy successful';
$lang->zanode->manual = 'Manual';
$lang->zanode->initializing = 'Initializing';
$lang->zanode->showPwd = 'Show Password';
$lang->zanode->hidePwd = 'Hide Password';
$lang->automation = new stdClass();
$lang->automation->scriptPath = $lang->zanode->scriptPath;
@@ -79,7 +83,25 @@ $lang->zanode->createImageSuccess = 'Successed, You can use this image to create
$lang->zanode->createImageFail = 'Failed to create';
$lang->zanode->createImageButton = 'Create image';
$lang->zanode->imageNameEmpty = 'Name can not be empty.';
$lang->zanode->snapshotName = 'Snapshot Name';
$lang->zanode->browseSnapshot = 'Snapshot List';
$lang->zanode->createSnapshot = 'Create Snapshot';
$lang->zanode->editSnapshot = 'Edit Snapshot';
$lang->zanode->restoreSnapshot = 'Revert Snapshot';
$lang->zanode->deleteSnapshot = 'Delete Snapshot';
$lang->zanode->snapshotEmpty = 'No snapshots';
$lang->zanode->confirmDeleteSnapshot = "The snapshot cannot be restored from the recycle bin after being deleted. Are you sure to continue?";
$lang->zanode->snapshot->statusList['creating'] = 'Creating';
$lang->zanode->snapshot->statusList['completed'] = 'Create Completed';
$lang->zanode->snapshot->statusList['failed'] = 'Create Failed';
$lang->zanode->snapshot->statusList['restoring'] = 'Restoring';
$lang->zanode->snapshot->statusList['restore_failed'] = 'Restore Failed';
$lang->zanode->snapshot->statusList['restore_completed'] = 'Restore Completed';
$lang->zanode->imageNameEmpty = 'Name can not be empty.';
$lang->zanode->snapStatusError = 'Snapshot is not ready.';
$lang->zanode->snapRestoring = 'Snapshot is restoring.';
$lang->zanode->runTimeout = 'Network connection timeout, please check the host and execution node status.';
@@ -101,6 +123,7 @@ $lang->zanode->statusList['shutodown'] = 'shutdown';
$lang->zanode->statusList['destroy_fail'] = 'Destroy Fail';
$lang->zanode->statusList['wait'] = 'Initializing';
$lang->zanode->statusList['online'] = 'Online';
$lang->zanode->statusList['restoring'] = 'Restoring';
$lang->zanode->initNotice = "Succeeded. Please initialize the execution node or return to the list.";
$lang->zanode->initButton = "Initialize";
+19
View File
@@ -59,6 +59,8 @@ $lang->zanode->copy = 'Click to copy';
$lang->zanode->copied = 'Copy successful';
$lang->zanode->manual = 'Manual';
$lang->zanode->initializing = 'Initializing';
$lang->zanode->showPwd = 'Show Password';
$lang->zanode->hidePwd = 'Hide Password';
$lang->automation = new stdClass();
$lang->automation->scriptPath = $lang->zanode->scriptPath;
@@ -79,6 +81,22 @@ $lang->zanode->createImageSuccess = 'Successed, You can use this image to create
$lang->zanode->createImageFail = 'Failed to create';
$lang->zanode->createImageButton = 'Create image';
$lang->zanode->snapshotName = 'Snapshot Name';
$lang->zanode->browseSnapshot = 'Snapshot List';
$lang->zanode->createSnapshot = 'Create Snapshot';
$lang->zanode->editSnapshot = 'Edit Snapshot';
$lang->zanode->restoreSnapshot = 'Revert Snapshot';
$lang->zanode->deleteSnapshot = 'Delete Snapshot';
$lang->zanode->snapshotEmpty = 'No snapshots';
$lang->zanode->confirmDeleteSnapshot = "The snapshot cannot be restored from the recycle bin after being deleted. Are you sure to continue?";
$lang->zanode->snapshot->statusList['creating'] = 'Creating';
$lang->zanode->snapshot->statusList['completed'] = 'Create Completed';
$lang->zanode->snapshot->statusList['failed'] = 'Create Failed';
$lang->zanode->snapshot->statusList['restoring'] = 'Restoring';
$lang->zanode->snapshot->statusList['restore_failed'] = 'Restore Failed';
$lang->zanode->snapshot->statusList['restore_completed'] = 'Restore Completed';
$lang->zanode->imageNameEmpty = 'Name can not be empty.';
$lang->zanode->runTimeout = 'Network connection timeout, please check the host and execution node status.';
@@ -101,6 +119,7 @@ $lang->zanode->statusList['shutodown'] = 'shutdown';
$lang->zanode->statusList['destroy_fail'] = 'Destroy Fail';
$lang->zanode->statusList['wait'] = 'Initializing';
$lang->zanode->statusList['online'] = 'Online';
$lang->zanode->statusList['restoring'] = 'Restoring';
$lang->zanode->initNotice = "Succeeded. Please initialize the execution node or return to the list.";
$lang->zanode->initButton = "Initialize";
+24
View File
@@ -48,6 +48,7 @@ $lang->zanode->confirmReboot = "您确定重启执行节点吗?";
$lang->zanode->confirmShutdown = "您确定关闭执行节点吗?";
$lang->zanode->confirmSuspend = "您确定休眠执行节点吗?";
$lang->zanode->confirmResume = "您确定恢复执行节点吗?";
$lang->zanode->confirmRestore = "执行节点将会还原至此快照状态,您确定要继续么?";
$lang->zanode->actionSuccess = '操作成功';
$lang->zanode->deleted = "已删除";
$lang->zanode->scriptPath = "脚本目录";
@@ -59,6 +60,8 @@ $lang->zanode->copy = '复制';
$lang->zanode->copied = '复制成功';
$lang->zanode->manual = '手册';
$lang->zanode->initializing = '初始化中';
$lang->zanode->showPwd = '显示密码';
$lang->zanode->hidePwd = '隐藏密码';
$lang->automation = new stdClass();
$lang->automation->scriptPath = $lang->zanode->scriptPath;
@@ -79,7 +82,27 @@ $lang->zanode->createImageSuccess = '镜像导出成功,您可以使用此镜
$lang->zanode->createImageFail = '镜像导出失败';
$lang->zanode->createImageButton = '去创建';
$lang->zanode->snapshotName = '快照名称';
$lang->zanode->browseSnapshot = '快照列表';
$lang->zanode->createSnapshot = '创建快照';
$lang->zanode->editSnapshot = '编辑快照';
$lang->zanode->restoreSnapshot = '还原快照';
$lang->zanode->deleteSnapshot = '删除快照';
$lang->zanode->snapshotEmpty = '无快照';
$lang->zanode->confirmDeleteSnapshot = "快照被删除后无法从回收站中还原,您确定继续么?";
$lang->zanode->snapshot = new stdClass();
$lang->zanode->snapshot->statusList['creating'] = '创建中';
$lang->zanode->snapshot->statusList['completed'] = '创建完成';
$lang->zanode->snapshot->statusList['failed'] = '创建失败';
$lang->zanode->snapshot->statusList['restoring'] = '还原中';
$lang->zanode->snapshot->statusList['restore_failed'] = '还原失败';
$lang->zanode->snapshot->statusList['restore_completed'] = '还原成功';
$lang->zanode->imageNameEmpty = '名称不能为空';
$lang->zanode->imageNameEmpty = '名称不能为空';
$lang->zanode->snapStatusError = '快照不可用';
$lang->zanode->snapRestoring = '快照正在还原中';
$lang->zanode->runTimeout = '自动执行失败,请检查宿主机和执行节点状态';
@@ -101,6 +124,7 @@ $lang->zanode->statusList['shutodown'] = '已关机';
$lang->zanode->statusList['destroy_fail'] = '销毁失败';
$lang->zanode->statusList['wait'] = '初始化中';
$lang->zanode->statusList['online'] = '已上架';
$lang->zanode->statusList['restoring'] = '还原中';
$lang->zanode->initNotice = "保存成功,请初始化执行节点或返回列表。";
$lang->zanode->initButton = "去初始化";
+193 -1
View File
@@ -28,6 +28,10 @@ class zanodemodel extends model
const KVM_EXPORT_PATH = '/api/v1/kvm/exportVm';
const KVM_STATUS_PATH = '/api/v1/task/getStatus';
const SNAPSHOT_CREATE_PATH = '/api/v1/kvm/addCreateSnap';
const SNAPSHOT_REVERT_PATH = '/api/v1/kvm/addRevertSnap';
const SNAPSHOT_REMOVE_PATH = '/api/v1/kvm/removeSnap';
/**
* Set lang;
*
@@ -167,6 +171,173 @@ class zanodemodel extends model
return false;
}
/**
* Create Snapshot by zanode.
*
* @param int $zanodeID
* @access public
* @return void
*/
public function createSnapshot($zanodeID = 0)
{
$data = fixer::input('post')->get();
if(empty($data->name)) dao::$errors['name'] = $this->lang->zanode->imageNameEmpty;
if(dao::isError()) return false;
$node = $this->getNodeByID($zanodeID);
$newSnapshot = new stdClass();
$newSnapshot->host = $node->id;
$newSnapshot->name = $data->name;
$newSnapshot->desc = $data->desc;
$newSnapshot->status = 'creating';
$newSnapshot->osName = $node->osName;
$newSnapshot->from = 'snapshot';
$newSnapshot->createdBy = $this->app->user->account;
$newSnapshot->createdDate = helper::now();
$this->dao->insert(TABLE_IMAGE)
->data($newSnapshot)
->autoCheck()
->exec();
if(dao::isError()) return false;
$newID = $this->dao->lastInsertID();
/* Prepare create params. */
$agnetUrl = 'http://' . $node->ip . ':' . $node->hzap;
$param = array(array(
'name' => $data->name,
'task' => $newID,
'type' => 'createSnap',
'vm' => $node->name
));
$result = json_decode(commonModel::http($agnetUrl . static::SNAPSHOT_CREATE_PATH, json_encode($param,JSON_NUMERIC_CHECK), null, array("Authorization:$node->tokenSN")));
if(!empty($result) and $result->code == 'success')
{
$this->loadModel('action')->create('zanode', $zanodeID, 'createdSnapshot', '', $data->name);
return $newID;
}
$this->dao->delete()->from(TABLE_IMAGE)->where('id')->eq($newID)->exec();
dao::$errors[] = (!empty($result) and !empty($result->msg)) ? $result->msg : $this->app->lang->fail;
return false;
}
/**
* Edit Snapshot.
*
* @param int $snapshotID
* @access public
* @return bool
*/
public function editSnapshot($snapshotID)
{
$data = fixer::input('post')->get();
if(empty($data->name)) dao::$errors['name'] = $this->lang->zanode->imageNameEmpty;
if(dao::isError()) return false;
$newSnapshot = new stdClass();
$newSnapshot->localName = $data->name;
$newSnapshot->desc = $data->desc;
$this->dao->update(TABLE_IMAGE)
->data($newSnapshot)
->where('id')->eq($snapshotID)
->autoCheck()
->exec();
return true;
}
/**
* Restore Snapshot to zanode.
*
* @param int $zanodeID
* @access public
* @return void
*/
public function restoreSnapshot($zanodeID = 0, $snapshotID = 0)
{
$node = $this->getNodeByID($zanodeID);
$snap = $this->getImageByID($snapshotID);
$snap->status = ($snap->status == 'restoring' && time() - strtotime($snap->restoreDate) > 600) ? 'restore_failed' : $snap->status;
if(!in_array($snap->status, array('completed', 'restoring', 'restore_failed', 'restore_completed'))) dao::$errors = $this->lang->zanode->snapStatusError;
if($snap->status == 'restoring') dao::$errors = $this->lang->zanode->snapRestoring;
if(dao::isError()) return false;
//update snapshot status
$this->dao->update(TABLE_IMAGE)
->set('status')->eq('restoring')
->set('restoreDate')->eq(helper::now())
->where('id')->eq($snapshotID)->exec();
/* Prepare create params. */
$agnetUrl = 'http://' . $node->ip . ':' . $node->hzap;
$param = array(array(
'name' => $snap->name,
'task' => $snapshotID,
'type' => 'revertSnap',
'vm' => $node->name
));
$result = json_decode(commonModel::http($agnetUrl . static::SNAPSHOT_CREATE_PATH, json_encode($param,JSON_NUMERIC_CHECK), null, array("Authorization:$node->tokenSN")));
if(!empty($result) and $result->code == 'success')
{
$this->dao->update(TABLE_HOST)->set('status')->eq('restoring')->where('id')->eq($node->id)->exec();
$this->loadModel('action')->create('zanode', $zanodeID, 'restoredsnapshot', '', $snap->name);
return true;
}
$this->dao->update(TABLE_IMAGE)->set('status')->eq('completed')->where('id')->eq($snapshotID)->exec();
dao::$errors[] = (!empty($result) and !empty($result->msg)) ? $result->msg : $this->lang->zanode->apiError['fail'];
return false;
}
/**
* Delete Snapshot.
*
* @param int $id
* @access public
* @return void
*/
public function deleteSnapshot($snapshotID)
{
$snapshot = $this->getImageByID($snapshotID);
$node = $this->getNodeByID($snapshot->host);
if($node)
{
$agnetUrl = 'http://' . $node->ip . ':' . $node->hzap;
$param = (object)array(
'name' => $snapshot->name,
'task' => $snapshotID,
'vm' => $node->name
);
$result = commonModel::http($agnetUrl . static::SNAPSHOT_REMOVE_PATH, json_encode($param,JSON_NUMERIC_CHECK), array(), array("Authorization:$node->tokenSN"));
$result = json_decode($result);
if(!empty($result) and $result->code == 'success')
{
$this->dao->delete()->from(TABLE_IMAGE)->where('id')->eq($snapshotID)->exec();
$this->loadModel('action')->create('zanode', $node->id, 'deletesnapshot', '', $snapshot->name);
return true;
}
$error = (!empty($result) and !empty($result->msg)) ? $result->msg : $this->lang->zanode->apiError['fail'];
return $error;
}
}
/**
* Action Node.
*
@@ -212,7 +383,7 @@ class zanodemodel extends model
public function destroy($id)
{
$node = $this->getNodeByID($id);
if($node)
{
$req = array( 'name' => $node->name );
@@ -520,6 +691,27 @@ class zanodemodel extends model
->fetch();
}
public function getSnapshotList($nodeID, $browseType = 'all', $param = 0, $orderBy = 'id', $pager = null)
{
$snapshotList = $this->dao->select('*')->from(TABLE_IMAGE)
->where('host')->eq($nodeID)
->andWhere('`from`')->eq('snapshot')
->orderBy($orderBy)
->page($pager)
->fetchAll('name');
foreach($snapshotList as $name => $snapshot)
{
if($snapshot->status == 'creating' and (time() - strtotime($snapshot->createdDate)) > 1800)
{
$this->dao->update(TABLE_IMAGE)->set('status')->eq('failed')->where('id')->eq($snapshot->id)->exec();
$snapshotList[$name]->status = 'failed';
}
}
return $snapshotList;
}
/**
* Get Node by id.
*
+5 -1
View File
@@ -85,6 +85,9 @@
$rebootAttr = "title='{$lang->zanode->reboot}' target='hiddenwin'";
$rebootAttr .= $node->status == 'shutoff' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmReboot}\")==false) return false;'";
$snapshotAttr = "title='{$lang->zanode->createSnapshot}'";
$snapshotAttr .= $node->status != 'running' ? ' class="btn disabled"' : ' class="btn iframe"';
common::printLink('zanode', 'getVNC', "id={$node->id}", "<i class='icon icon-remote'></i> ", (in_array($node->status ,array('running', 'launch', 'wait')) ? '_blank' : ''), "title='{$lang->zanode->getVNC}' class='btn desktop " . (in_array($node->status ,array('running', 'launch', 'wait')) ? '':'disabled') . "'", '');
if($node->status == "suspend")
{
@@ -105,13 +108,14 @@
}
common::printLink('zanode', 'reboot', "zanodeID={$node->id}", "<i class='icon icon-restart'></i> ", '', $rebootAttr);
common::printIcon('zanode', 'edit', "id={$node->id}", $node, 'list');
common::printLink('zanode', 'createSnapshot', "zanodeID={$node->id}", "<i class='icon icon-plus'></i> ", '', $snapshotAttr, true, true);
if(common::hasPriv('zanode', 'createImage') or common::hasPriv('zanode', 'destroy'))
{
echo "<div class='btn-group'>";
echo "<button type='button' class='btn dropdown-toggle' data-toggle='context-dropdown' title='{$this->lang->more}'><i class='icon-ellipsis-v'></i></button>";
echo "<ul class='dropdown-menu pull-right text-center' role='menu'>";
common::printIcon('zanode', 'edit', "id={$node->id}", $node, 'list', '', '', 'btn-action');
common::printLink('zanode', 'createImage', "zanodeID={$node->id}", "<i class='icon icon-export'></i> ", '', "class='btn btn-action iframe createImage' title='{$lang->zanode->createImage}' data-width='55%'", '', true);
common::printLink('zanode', 'destroy', "zanodeID={$node->id}", "<i class='icon icon-trash'></i> ", '', "title='{$lang->zanode->destroy}' class='btn btn-action' target='hiddenwin'");
echo "</ul>";
@@ -0,0 +1,66 @@
<?php
/**
* The snapshot browse view file of zahost module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author xiawenlong <liyuchun@easycorp.ltd>
* @package zahost
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<?php js::set('nodeID', $nodeID);?>
<div id='mainContent' class='main-table'>
<?php $vars = "nodeID=$nodeID&browseType=all&param=0&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}";?>
<?php if(empty($snapshotList)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->zanode->snapshotEmpty;?></span>
</p>
</div>
<?php else:?>
<table class='table has-sort-head table-fixed' id='snapshotList'>
<thead>
<tr>
<th class='c-name'><?php common::printOrderLink('name', $orderBy, $vars, $lang->zahost->image->name);?></th>
<th class='c-status'><?php echo $lang->zahost->status;?></th>
<th class='c-createdBy'><?php echo $lang->zahost->createdBy;?></th>
<th class='c-datetime'><?php echo $lang->zahost->createdDate;?></th>
<th class='c-actions-3'><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
<?php foreach($snapshotList as $snapshot):?>
<tr>
<?php
$snapshot->status = ($snapshot->status == 'restoring' && time() - strtotime($snapshot->restoreDate) > 600) ? 'restore_failed' : $snapshot->status;
$editAttr = $snapshot->status == 'failed' ? 'class="btn disabled"' : "title={$lang->zanode->editSnapshot} onclick='window.parent.editSnapshot(\"" . $this->createLink('zanode', 'editSnapshot', "snapshotID={$snapshot->id}") . "\")' class='btn'";
$restoreAttr = "title='{$lang->zanode->restoreSnapshot}' target='hiddenwin'";
$restoreAttr .= ($node->status !='running' or $snapshot->status == 'restoring' or $snapshot->status == 'failed') ? ' class="btn disabled"' : 'class="btn"';
$deleteAttr = "title='{$lang->zanode->deleteSnapshot}' target='hiddenwin'";
$deleteAttr .= (($snapshot->status == 'restoring' and (time() - strtotime($snapshot->restoreDate)) <= 600) or $snapshot->status == 'failed') ? ' class="btn disabled"' : 'class="btn"';
?>
<td title="<?php echo $snapshot->name;?>"><?php echo $snapshot->localName ? $snapshot->localName : $snapshot->name;?></td>
<td class='<?php echo $snapshot->status;?>'><?php echo zget($lang->zanode->snapshot->statusList, $snapshot->status, '');?></td>
<td class="c-createdBy"><?php echo zget($users, $snapshot->createdBy, '')?></td>
<td class='c-datetime'><?php echo $snapshot->createdDate;?></td>
<td class='c-actions'>
<?php if(common::hasPriv('zanode', 'editSnapshot')) echo html::a('###', '<i class="icon-edit"></i>', 'hiddenwin', $editAttr);?>
<?php if(common::hasPriv('zanode', 'restoreSnapshot')) echo html::a($this->createLink('zanode', 'restoreSnapshot', "nodeID={$nodeID}&snapshotID={$snapshot->id}"), '<i class="icon-restart"></i>', 'hiddenwin', $restoreAttr);?>
<?php if(common::hasPriv('zanode', 'deleteSnapshot')) echo html::a($this->createLink('zanode', 'deleteSnapshot', "snapshotID={$snapshot->id}"), '<i class="icon-trash"></i>', 'hiddenwin', $deleteAttr);?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='table-footer'>
<?php $pager->show('right', 'pagerjs');?>
</div>
<?php endif;?>
</div>
<?php include $app->getModuleRoot() . 'common/view/footer.html.php';?>
@@ -0,0 +1,46 @@
<?php
/**
* The create file of snapshot of zanode.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author chunsheng wang <chunsheng@cnezsoft.com>
* @package task
* @version
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('nodeID', $node->id);?>
<?php js::set('zanodeLang', $lang->zanode); ?>
<style>.body-modal #mainContent{width:90%}
</style>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2>
<span><?php echo $lang->zanode->createSnapshot;?></span>
</h2>
</div>
<form class="load-indicator main-form form-ajax" method='post' enctype='multipart/form-data' id='dataform'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->zanode->snapshotName;?></th>
<td class='required'><?php echo html::input('name', '', "class='form-control'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->zanode->desc;?></th>
<td colspan='2'><?php echo html::textarea('desc', '', "rows='6' class='form-control'");?></td>
</tr>
<tr>
<td colspan='3' class='text-center'>
<?php echo html::submitButton('', "");?>
</td>
</tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+45
View File
@@ -0,0 +1,45 @@
<?php
/**
* The edit file of snapshot of zanode.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author chunsheng wang <chunsheng@cnezsoft.com>
* @package task
* @version
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('zanodeLang', $lang->zanode); ?>
<style>.body-modal #mainContent{width:90%}
</style>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2>
<span><?php echo $lang->zanode->editSnapshot;?></span>
</h2>
</div>
<form class="load-indicator main-form form-ajax" method='post' enctype='multipart/form-data' id='dataform'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->zanode->snapshotName;?></th>
<td class='required'><?php echo html::input('name', $snapshot->localName ? $snapshot->localName : $snapshot->name, "class='form-control'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->zanode->desc;?></th>
<td colspan='2'><?php echo html::textarea('desc', $snapshot->desc, "rows='6' class='form-control'");?></td>
</tr>
<tr>
<td colspan='3' class='text-center'>
<?php echo html::submitButton('', "");?>
</td>
</tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+1
View File
@@ -11,6 +11,7 @@
* @link http://www.zentao.net
*/
?>
<?php js::set('showFeature', false);?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php'; ?>
<div id='mainContent' class='main-table'>
<?php $vars = "id={$hostID}&orderBy=%s"; ?>
+26 -2
View File
@@ -55,7 +55,7 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
<div class="col-4">
<div class="main-row">
<div class="col-3 text-right"><?php echo $lang->zanode->sshAddress; ?>:</div>
<div class="col-8 node-not-wrap">ssh <?php echo $account . '@' . $zanode->ip . ' -p ' . $zanode->ssh; ?><?php echo " <button type='button' class='btn btn-info btn-mini btn-ssh-copy'><i class='icon-common-copy icon-copy' title='" . $lang->zanode->copy . "'></i></button>"; ?></div>
<div class="col-8 node-not-wrap"><?php echo $zanode->ssh ? 'ssh ' . $account . '@' . $zanode->ip . ' -p ' . $zanode->ssh : ''; ?><?php echo $zanode->ssh ? " <button type='button' class='btn btn-info btn-mini btn-ssh-copy'><i class='icon-common-copy icon-copy' title='" . $lang->zanode->copy . "'></i></button>" : ''; ?></div>
</div>
<textarea style="display:none;" id="ssh-copy">ssh <?php echo $account . '@' . $zanode->ip . ' -p ' . $zanode->ssh; ?></textarea>
</div>
@@ -96,7 +96,12 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
<div class="col-4">
<div class="main-row">
<div class="col-3 text-right"><?php echo $lang->zanode->defaultPwd; ?>:</div>
<div class="col-8"><?php echo $config->zanode->defaultPwd . ' ' . "<button type='button' class='btn btn-info btn-mini btn-pwd-copy'><i class='icon-common-copy icon-copy' title='" . $lang->zanode->copy . "'></i></button>"; ?></div>
<div class="col-8 default-pwd"><?php
echo '<span id="pwd-text">' . str_repeat('*', strlen($config->zanode->defaultPwd)) . '</span>'
. ' '
. "<button type='button' class='btn btn-info btn-mini btn-pwd-copy'><i class='icon-common-copy icon-copy' title='" . $lang->zanode->copy . "'></i></button>"
. "<button type='button' class='btn btn-info btn-mini btn-pwd-show'><i class='icon-common-eye icon-eye' title='" . $lang->zanode->showPwd . "'></i></button>";
?></div>
<textarea style="display:none;" id="pwd-copy"><?php echo $config->zanode->defaultPwd; ?></textarea>
</div>
</div>
@@ -149,6 +154,20 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
<div class="detail-content article-content"><?php echo !empty($zanode->desc) ? htmlspecialchars_decode($zanode->desc) : $lang->noData; ?></div>
</div>
</div>
<?php if(common::hasPriv('zanode', 'browseSnapshot')):?>
<div class="cell">
<div class="detail zanode-detail">
<div class="detail-title"><?php echo $lang->zanode->browseSnapshot;?></div>
<?php if(!empty($snapshotList)): ?>
<div class="detail-content article-content">
<?php echo "<iframe width='100%' id='nodesIframe' src='" . $this->createLink('zanode', 'browseSnapshot', "nodeID=$zanode->id", '', true) . "' frameborder='no' allowfullscreen='true' mozallowfullscreen='true' webkitallowfullscreen='true' allowtransparency='true' scrolling='auto' style='min-height:300px;'></iframe>";?>
</div>
<?php else: ?>
<div class="detail-content article-content"><?php echo $lang->noData; ?></div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php $this->printExtendFields($zanode, 'div', "position=left&inForm=0&inCell=1"); ?>
<div class='main-actions'>
<div class="btn-toolbar">
@@ -164,6 +183,9 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
$rebootAttr = "title='{$lang->zanode->reboot}' target='hiddenwin'";
$rebootAttr .= $zanode->status == 'shutoff' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmReboot}\")==false) return false;'";
$snapshotAttr = "title='{$lang->zanode->createSnapshot}'";
$snapshotAttr .= $zanode->status != 'running' ? ' class="btn disabled"' : ' class="btn iframe"';
common::printLink('zanode', 'getVNC', "id={$zanode->id}", "<i class='icon icon-remote'></i> " . $lang->zanode->getVNC, in_array($zanode->status ,array('running', 'launch', 'wait')) ? '_blank' : '', "title='{$lang->zanode->getVNC}' class='btn desktop " . (in_array($zanode->status ,array('running', 'launch', 'wait')) ? '':'disabled') . "'", '');
if($zanode->status == "suspend")
@@ -185,11 +207,13 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
}
common::printLink('zanode', 'reboot', "zanodeID={$zanode->id}", "<i class='icon icon-restart'></i> " . $lang->zanode->rebootNode, '', $rebootAttr);
common::printLink('zanode', 'createSnapshot', "zanodeID={$zanode->id}", "<i class='icon icon-plus'></i> " . $lang->zanode->createSnapshot, '', $snapshotAttr, true, true);
}
?>
<div class='divider'></div>
<?php echo $this->zanode->buildOperateMenu($zanode, 'view'); ?>
<a id='editSnapshot' href='' class='iframe'></a>
</div>
</div>
</div>
+1
View File
@@ -15,6 +15,7 @@ class prepareUpdate
public function __construct()
{
$this->initZT();
$this->initMysql();
$this->addChangelog();
$this->changeVersion();
$this->addReleaseDetail();
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
v7.0.0
v7.1.0
+1 -1
View File
@@ -1 +1 @@
7.0
7.1