Merge branch 'zentaopms_289' of https://gitlab.zcorp.cc/easycorp/zentaopms into zentaopms_289
This commit is contained in:
@@ -84,6 +84,19 @@ class hostHeartbeatEntry extends baseEntry
|
||||
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();
|
||||
|
||||
if($vm->status == 'running')
|
||||
{
|
||||
$node = $this->loadModel('zanode')->getNodeByMac($vm->macAddress);
|
||||
if(!empty($node))
|
||||
{
|
||||
$snaps = $this->loadModel('zanode')->getSnapshotList($node->id);
|
||||
if(empty($snaps))
|
||||
{
|
||||
if($vm->status == 'running') $this->loadModel('zanode')->createDefaultSnapshot($node->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,13 +40,21 @@ class hostSubmitEntry extends baseEntry
|
||||
|
||||
if(!$id) return $this->sendError(400, 'Secret error.');
|
||||
|
||||
$imageInfo = $this->dao->select('`status`,`from`')->from(TABLE_IMAGE)
|
||||
$imageInfo = $this->dao->select('`status`,`from`', 'name')->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';
|
||||
if(in_array($image->status, array('failed', 'completed'))) $image->status = $image->status == 'completed' ? 'restore_completed' : 'restore_failed';
|
||||
}
|
||||
else if($imageInfo->from == 'snapshot' && $imageInfo->status == 'creating')
|
||||
{
|
||||
if($image->status == 'failed')
|
||||
{
|
||||
$this->dao->delete()->from(TABLE_IMAGE)->where("id")->eq($task)->exec();
|
||||
return $this->sendSuccess(200, 'success');
|
||||
}
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_IMAGE)->data($image)->where("id")->eq($task)->exec();
|
||||
|
||||
@@ -406,6 +406,7 @@ $config->objectTables['apistruct'] = TABLE_APISTRUCT;
|
||||
$config->objectTables['repo'] = TABLE_REPO;
|
||||
$config->objectTables['dataview'] = TABLE_DATAVIEW;
|
||||
$config->objectTables['zahost'] = TABLE_ZAHOST;
|
||||
$config->objectTables['zanode'] = TABLE_ZAHOST;
|
||||
$config->objectTables['automation'] = TABLE_AUTOMATION;
|
||||
$config->objectTables['stepResult'] = TABLE_TESTRUN;
|
||||
|
||||
|
||||
+3
-8
@@ -2161,6 +2161,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(1,'custom','project'),
|
||||
(1,'custom','restore'),
|
||||
(1,'custom','set'),
|
||||
(1,'custom','hours'),
|
||||
(1,'custom','setDefaultConcept'),
|
||||
(1,'custom','setPublic'),
|
||||
(1,'custom','setStoryConcept'),
|
||||
@@ -2753,6 +2754,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(2,'custom','product'),
|
||||
(2,'custom','restore'),
|
||||
(2,'custom','set'),
|
||||
(2,'custom','hours'),
|
||||
(2,'custom','setPublic'),
|
||||
(2,'datatable','setGlobal'),
|
||||
(2,'dept','browse'),
|
||||
@@ -6383,14 +6385,7 @@ REPLACE INTO `zt_lang` (`lang`, `module`, `section`, `key`, `value`, `system`) V
|
||||
('zh-cn', 'custom', 'URSRList', '3', '{\"SRName\":\"\\u8f6f\\u9700\",\"URName\":\"\\u7528\\u9700\"}', '1'),('zh-cn', 'custom', 'URSRList', '4', '{\"SRName\":\"\\u6545\\u4e8b\",\"URName\":\"\\u53f2\\u8bd7\"}', '1'),
|
||||
('zh-cn', 'custom', 'URSRList', '5', '{\"SRName\":\"\\u9700\\u6c42\",\"URName\":\"\\u7528\\u6237\\u9700\\u6c42\"}', '1'),
|
||||
('en', 'custom', 'URSRList', '1', '{\"SRName\":\"Story\",\"URName\":\"Epic\"}', '0'),
|
||||
('en', 'custom', 'URSRList', '2', '{\"SRName\":\"Software Requirement\",\"URName\":\"User Requirement\"}', '0'),
|
||||
('all','stage','typeList','request','需求', '1'),
|
||||
('all','stage','typeList','design','设计', '1'),
|
||||
('all','stage','typeList','dev','开发', '1'),
|
||||
('all','stage','typeList','qa','测试', '1'),
|
||||
('all','stage','typeList','release','发布', '1'),
|
||||
('all','stage','typeList','review','总结评审','1'),
|
||||
('all','stage','typeList','other','其他','1');
|
||||
('en', 'custom', 'URSRList', '2', '{\"SRName\":\"Software Requirement\",\"URName\":\"User Requirement\"}', '0');
|
||||
|
||||
REPLACE INTO `zt_stage` (`name`,`percent`,`type`,`projectType`,`createdBy`,`createdDate`,`editedBy`,`editedDate`,`deleted`) VALUES
|
||||
('需求','10','request','waterfall','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
|
||||
|
||||
@@ -130,6 +130,102 @@
|
||||
修复的Bug
|
||||
开源版:
|
||||
32397 地盘待处理任务搜索界面报错
|
||||
企业版:
|
||||
18695 bug重新步骤有图片,导出mht没有图片
|
||||
22568 特殊情况下,上线中不显示添加的计划
|
||||
23227 导出xls格式模板部门字段点击下拉控件无反应
|
||||
23588 反馈列表批量编辑时,所属产品作为必填项为空时可以保存
|
||||
24026 导出的word中显示多余的空行
|
||||
24733 反馈转待办页面,提示关联编号不能为空
|
||||
24881 没有详情权限时,历史记录中不应展示链接
|
||||
24897 切换左侧筛选标签,上方标签统计数字消失
|
||||
24932 自定义切换语言未选中“适用当前语言”
|
||||
24935 只有默认反馈关闭原因,切换到法语,语言项有问题
|
||||
24944 没有详情页权限,点击历史记录提示没权限
|
||||
24997 追问时提示回复内容不能为空
|
||||
25008 需求详情页弹窗,撤销评审后变空白页了
|
||||
25010 任务列表详情页弹窗,返回按钮点击没反应
|
||||
25017 导出用例时<>会被转义为<>
|
||||
25082 用例导入是带有<>符号时显示异常
|
||||
25104 反馈指派后,指派人在反馈列表看不到指派的反馈
|
||||
25183 测试用例下从用例库导入的用例未同步到项目测试用例下
|
||||
25251 代码评审详情页转任务时提示信息不合理
|
||||
25442 账号页面搜索条件选择由谁添加/编辑时未列出系统用户
|
||||
25468 反馈列表,创建人字段鼠标悬浮不能显示title
|
||||
25475 法语下创建FAQ按钮语言项错误
|
||||
25853 用例详情页显示了导入用例库按钮
|
||||
25883 地盘-日志,点击任意日期添加日志遮罩无反应
|
||||
26140 wiki文档搜索结果错误
|
||||
26147 法语下切换研发综合界面和迅捷界面报错
|
||||
26227 一个Bug有多个附件时,导出后多个附件显示在多列了
|
||||
26341 用户需求列表导出显示了“所属计划”字段
|
||||
26422 数据富文本字段中带有表格时,导出xlsx表格中列宽太宽
|
||||
26427 导出项目下研发需求模块和计划显示不正确
|
||||
26432 导入需求评审人可以选择所有产品成员
|
||||
26435 导出的用例库模板中显示了产品的所属模块
|
||||
26436 测试用例库导出模板没有包含模块的系统数据
|
||||
26439 项目测试下导入的用例只显示了测试视图下的用例列表中
|
||||
26440 导出任务,来源Bug字段只显示了Bug的id
|
||||
26444 工作流导出模板后导入后,提示没有有效数据
|
||||
26446 新增工作流下载模板,里面的字段不对
|
||||
26552 文档的上一篇按钮显示缺失
|
||||
26568 用例导出特殊字符会异常
|
||||
26680 执行甘特图中按钮无图标
|
||||
26855 导入时,关掉错误提示弹框,导入按钮置灰
|
||||
27039 批量编辑反馈时指派给显示了closed
|
||||
27113 英文下反馈标签栏换行显示
|
||||
27119 反馈转待办,完成待办后动态中缺少语言项
|
||||
27127 编辑执行和创建执行可用工作日逻辑不一致
|
||||
27207 创建反馈时产品的下拉列表显示顺序和反馈权限列表顺序不一致
|
||||
27322 导出反馈数据,数据中字段没有进行重新排序
|
||||
27571 执行视图分组视图导出的任务列表相关研发需求丢失
|
||||
28630 反馈列表选择产品后,创建反馈时没有显示已选产品
|
||||
28680 创建反馈页面选择产品下拉菜单中产品顺序不正确
|
||||
28722 编辑反馈时没有显示来源公司字段
|
||||
28773 产品模块下的反馈转研发需求/用户需求时,模块没有自动带出来
|
||||
28780 新增日志时工作内容输入空格可以保存成功
|
||||
28804 工单详情页来源字段处,反馈编号前建议增加“#”
|
||||
28869 导入用例相关研发需求换行显示
|
||||
28890 反馈列表操作按钮换行
|
||||
32093 影响版本下拉单选多选不固定
|
||||
32098 反馈同步产品模块,反馈模块太长不能完全显示
|
||||
旗舰版:
|
||||
24152 新增自定义严重程度时,QA执行检查时严重程度显示被遮挡
|
||||
24499 添加一个风险区块按照状态倒叙排序,默认排序与手动状态倒叙排序不一致
|
||||
24525 审批流中选择多个审批人,发起审批时只显示第一个
|
||||
24577 审批流中审批类型为角色,发起审批时不显示
|
||||
24723 会议生成的日程没有创建日程的历史记录
|
||||
24816 德语法语下资产库操作栏菜单显示不全
|
||||
24872 资产库预览文档时切换BIG5格式不成功
|
||||
25127 评审的问题列表选择评审项后,评审项显示不完整
|
||||
25477 过程名称很长时在左侧检查对象区块中显示问题
|
||||
25654 QA质量保证计划再次编辑时,不能看到上次填写的备注
|
||||
25966 点击上一步回到基础信息页面后,部分信息显示不正确
|
||||
25976 阶段的访问控制改为私有后,当前用户也看不到该阶段了
|
||||
26041 会议记录页面只显示了在该页面上传的附件
|
||||
26288 待处理/贡献、组织团队下的风险列表中风险系数和优先级样式未调整
|
||||
26474 升级禅道15系列介绍页面视频下方的空白建议调小点
|
||||
26577 基线评审,概要设计名称中含有“-”,获取系统数据会有问题
|
||||
26615 工期估算页面展示的界面错误导致无法保存
|
||||
27355 质量保证计划检查结果为否,未校验严重程度是否为空
|
||||
29011 问题详情页未指派样式建议优化
|
||||
29169 费用估算列表的阶段字段换行显示
|
||||
29222 分页查看执行附件库时,跳转到文档执行库下
|
||||
29413 费用估算列表页中阶段名称换行了
|
||||
30351 工作流增加富文本字段,导出后带有html标签,可读性差
|
||||
30843 旗舰版瀑布项目阶段排序后,甘特图不会同步
|
||||
30912 设置阶段时,输出选择多项后整个页面样式不友好
|
||||
31059 火狐浏览器设计审批流页面添加审批节点后页面显示不全不能滑动显示
|
||||
31414 审批流浏览器通知,有多条重复标题
|
||||
31425 浏览器通知中未显示名称
|
||||
31443 任务删除时,同时删除依赖关系
|
||||
31941 正在审批的流程显示了上一次审批节点的结果
|
||||
31943 项目型项目发起研发需求评审,评审页面无结构化评审内容
|
||||
31957 回收站中点击评审问题,详情页中有解决按钮
|
||||
31962 删除的文档/活动没有标记已删除
|
||||
31964 复制项目型项目提示关联产品或创建产品
|
||||
31996 后台过程列表执行搜索后,模型的二级导航下拉菜单高亮了两个
|
||||
32117 配置项删除按钮与系统的不一致
|
||||
|
||||
2023-02-08 18.1
|
||||
完成的需求
|
||||
|
||||
@@ -938,6 +938,8 @@ class actionModel extends model
|
||||
}
|
||||
else
|
||||
{
|
||||
if($actionType == 'restoredsnapshot' && in_array($action->objectType, array('vm', 'zanode')) && $value == 'defaultSnap') $value = $this->lang->$objectType->snapshot->defaultSnapName;
|
||||
|
||||
$desc = str_replace('$' . $key, $value, $desc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ if(!isset($config->safe)) $config->safe = new stdclass();
|
||||
if(!isset($config->safe->weak)) $config->safe->weak = '123456,password,12345,12345678,qwerty,123456789,1234,1234567,abc123,111111,123123';
|
||||
|
||||
$config->admin->menuGroup['system'] = array('custom|mode', 'backup', 'cron', 'action|trash', 'admin|xuanxuan', 'setting|xuanxuan', 'admin|license', 'admin|checkweak', 'admin|resetpwdsetting', 'admin|safe', 'custom|timezone', 'search|buildindex', 'admin|tableengine', 'ldap', 'custom|libreoffice', 'conference', 'client');
|
||||
$config->admin->menuGroup['user'] = array('dept', 'company', 'user', 'group');
|
||||
$config->admin->menuGroup['company'] = array('dept', 'company', 'user', 'group', 'tutorial');
|
||||
$config->admin->menuGroup['switch'] = array('admin|setmodule');
|
||||
$config->admin->menuGroup['model'] = array('auditcl', 'stage', 'design', 'cmcl', 'reviewcl', 'custom|required', 'custom|set', 'custom|flow', 'custom|code', 'custom|estimate', 'custom|hours', 'subject', 'process', 'activity', 'zoutput', 'classify', 'holiday', 'reviewsetting');
|
||||
$config->admin->menuGroup['feature'] = array('custom|set', 'custom|product', 'custom|execution', 'custom|required', 'custom|kanban', 'approvalflow', 'measurement', 'meetingroom', 'custom|browsestoryconcept', 'custom|kanban', 'sqlbuilder', 'report');
|
||||
@@ -72,14 +72,14 @@ $config->admin->extAPIURL = $config->admin->apiSite . 'extension-apiGetExte
|
||||
$config->admin->patchAPIURL = $config->admin->apiSite . 'extension-apiGetExtensions-bymodule-MTIxOA==-0-100-1.json';
|
||||
$config->admin->downloadAPIURL = $config->admin->apiSite . 'download.json';
|
||||
$config->admin->videoAPIURL = $config->admin->apiSite . 'publicclass.json';
|
||||
$config->admin->liteMenuList = array('system', 'user', 'feature', 'message', 'extension', 'dev');
|
||||
$config->admin->liteMenuList = array('system', 'company', 'feature', 'message', 'extension', 'dev');
|
||||
|
||||
$config->admin->helpURL['system'] = 'https://www.zentao.net/book/zentaopms/538.html';
|
||||
$config->admin->helpURL['user'] = 'https://www.zentao.net/book/zentaopms/538.html';
|
||||
$config->admin->helpURL['switch'] = 'https://www.zentao.net/book/zentaopms/538.html';
|
||||
$config->admin->helpURL['company'] = 'https://www.zentao.net/book/zentaopms/38.html';
|
||||
$config->admin->helpURL['switch'] = 'https://www.zentao.net/book/zentaopms/38.html';
|
||||
$config->admin->helpURL['model'] = 'https://www.zentao.net/book/zentaopms/533.html';
|
||||
$config->admin->helpURL['feature'] = 'https://www.zentao.net/book/zentaopms/538.html';
|
||||
$config->admin->helpURL['template'] = 'https://www.zentao.net/book/zentaopms/538.html';
|
||||
$config->admin->helpURL['feature'] = 'https://www.zentao.net/book/zentaopms/38.html';
|
||||
$config->admin->helpURL['template'] = 'https://www.zentao.net/book/zentaopms/38.html';
|
||||
$config->admin->helpURL['message'] = 'https://www.zentao.net/book/zentaopms/email-notification-541.html';
|
||||
$config->admin->helpURL['extension'] = 'https://www.zentao.net/book/zentaopms/536.html';
|
||||
$config->admin->helpURL['dev'] = 'https://www.zentao.net/book/zentaopms/537.html';
|
||||
|
||||
@@ -41,7 +41,9 @@
|
||||
.settings-list > .setting-box > button.btn {padding: 5px 10px; height: 100%; width: 100%; display: flex; flex-direction: column; justify-content: space-between; cursor: pointer; white-space: unset; text-align: unset; border: 1px solid rgba(227, 228, 233, 0.6)}
|
||||
.settings-list > .setting-box > .btn:hover {background: unset;}
|
||||
.settings-list > .setting-box > .btn[disabled] {cursor: not-allowed; pointer-events: unset;}
|
||||
.settings-list > .setting-box > .btn[disabled] > a {pointer-events: none;}
|
||||
.settings-list > .setting-box > .btn[disabled] > a,
|
||||
.settings-list > .setting-box > .btn[disabled] a.setting-help,
|
||||
.settings-list > .setting-box > .btn[disabled] p.setting-desc {pointer-events: none;}
|
||||
.settings-list > .setting-box > .btn > h4 {padding-right: 5px;}
|
||||
.settings-list > .setting-box > .btn > h4 > div {gap: 3px;}
|
||||
.settings-list > .setting-box > .btn > h4 > img {padding-right: 8px; padding-bottom: 3px; width: 32px; height: 27px;}
|
||||
|
||||
@@ -66,7 +66,7 @@ $lang->admin->notice->ignore = "Ignorieren";
|
||||
$lang->admin->notice->int = "『%s』sollte eine positive Zahl sein.";
|
||||
|
||||
$lang->admin->registerNotice = new stdclass();
|
||||
$lang->admin->registerNotice->common = 'Verbinde neues Konto';
|
||||
$lang->admin->registerNotice->common = 'Register Account';
|
||||
$lang->admin->registerNotice->caption = 'In der Zentao Community registieren';
|
||||
$lang->admin->registerNotice->click = 'Bitte registieren Sie sich hier';
|
||||
$lang->admin->registerNotice->lblAccount = 'mindestens 3 Zeichen bitte; mit Buchsten und Ziffern.';
|
||||
@@ -186,6 +186,7 @@ $lang->admin->updateDynamics = 'Dynamics';
|
||||
$lang->admin->updatePatch = 'Patch';
|
||||
$lang->admin->upgradeRecommend = 'Recommend Upgrade';
|
||||
$lang->admin->zentaoUsed = 'You have used ZenTao';
|
||||
$lang->admin->noPriv = 'You have no permission to visit this block.';
|
||||
|
||||
$lang->admin->openTag = 'ZenTao Opensource ';
|
||||
$lang->admin->bizTag = 'ZenTao Biz ';
|
||||
|
||||
@@ -66,7 +66,7 @@ $lang->admin->notice->ignore = "Ignore";
|
||||
$lang->admin->notice->int = "『%s』should be a positive integer.";
|
||||
|
||||
$lang->admin->registerNotice = new stdclass();
|
||||
$lang->admin->registerNotice->common = 'Bind Account';
|
||||
$lang->admin->registerNotice->common = 'Register Account';
|
||||
$lang->admin->registerNotice->caption = 'ZenTao Community Signup';
|
||||
$lang->admin->registerNotice->click = 'Sign Up';
|
||||
$lang->admin->registerNotice->lblAccount = '>= 3 letters and numbers';
|
||||
@@ -186,6 +186,7 @@ $lang->admin->updateDynamics = 'Dynamics';
|
||||
$lang->admin->updatePatch = 'Patch';
|
||||
$lang->admin->upgradeRecommend = 'Recommend Upgrade';
|
||||
$lang->admin->zentaoUsed = 'You have used ZenTao';
|
||||
$lang->admin->noPriv = 'You have no permission to visit this block.';
|
||||
|
||||
$lang->admin->openTag = 'ZenTao Opensource ';
|
||||
$lang->admin->bizTag = 'ZenTao Biz ';
|
||||
|
||||
@@ -66,7 +66,7 @@ $lang->admin->notice->ignore = "Ignorer";
|
||||
$lang->admin->notice->int = "『 %s 』 devrait être un entier positif.";
|
||||
|
||||
$lang->admin->registerNotice = new stdclass();
|
||||
$lang->admin->registerNotice->common = 'Connectez-vous avec votre nouveau compte';
|
||||
$lang->admin->registerNotice->common = 'Register Account';
|
||||
$lang->admin->registerNotice->caption = "S'enregistrer sur la communauté Zentao";
|
||||
$lang->admin->registerNotice->click = "S'enregistrer ici";
|
||||
$lang->admin->registerNotice->lblAccount = '>= 3 lettres et chiffres';
|
||||
@@ -186,6 +186,7 @@ $lang->admin->updateDynamics = 'Dynamics';
|
||||
$lang->admin->updatePatch = 'Patch';
|
||||
$lang->admin->upgradeRecommend = 'Recommend Upgrade';
|
||||
$lang->admin->zentaoUsed = 'You have used ZenTao';
|
||||
$lang->admin->noPriv = 'You have no permission to visit this block.';
|
||||
|
||||
$lang->admin->openTag = 'ZenTao Opensource ';
|
||||
$lang->admin->bizTag = 'ZenTao Biz ';
|
||||
|
||||
+18
-17
@@ -10,9 +10,9 @@ $lang->admin->menuList->switch['desc'] = $lang->admin->menuSetting['switch']['d
|
||||
$lang->admin->menuList->switch['link'] = 'admin|setmodule';
|
||||
$lang->admin->menuList->switch['order'] = 10;
|
||||
|
||||
$lang->admin->menuList->user['name'] = $lang->admin->menuSetting['user']['name'];
|
||||
$lang->admin->menuList->user['desc'] = $lang->admin->menuSetting['user']['desc'];
|
||||
$lang->admin->menuList->user['order'] = 15;
|
||||
$lang->admin->menuList->company['name'] = $lang->admin->menuSetting['user']['name'];
|
||||
$lang->admin->menuList->company['desc'] = $lang->admin->menuSetting['user']['desc'];
|
||||
$lang->admin->menuList->company['order'] = 15;
|
||||
|
||||
$lang->admin->menuList->model['name'] = $lang->admin->menuSetting['model']['name'];
|
||||
$lang->admin->menuList->model['desc'] = $lang->admin->menuSetting['model']['desc'];
|
||||
@@ -64,13 +64,13 @@ $lang->admin->menuList->system['menuOrder']['50'] = 'tableengine';
|
||||
|
||||
$lang->admin->menuList->system['dividerMenu'] = ',safe,';
|
||||
|
||||
$lang->admin->menuList->user['subMenu']['dept'] = array('link' => "{$lang->dept->common}|dept|browse|", 'subModule' => 'dept');
|
||||
$lang->admin->menuList->user['subMenu']['user'] = array('link' => "{$lang->user->common}|company|browse|", 'subModule' => 'user');
|
||||
$lang->admin->menuList->user['subMenu']['group'] = array('link' => "{$lang->priv}|group|browse|", 'subModule' => 'group');
|
||||
$lang->admin->menuList->company['subMenu']['dept'] = array('link' => "{$lang->dept->common}|dept|browse|", 'subModule' => 'dept');
|
||||
$lang->admin->menuList->company['subMenu']['browseUser'] = array('link' => "{$lang->user->common}|company|browse|", 'subModule' => 'user,tutorial');
|
||||
$lang->admin->menuList->company['subMenu']['group'] = array('link' => "{$lang->priv}|group|browse|", 'subModule' => 'group');
|
||||
|
||||
$lang->admin->menuList->user['menuOrder']['5'] = 'dept';
|
||||
$lang->admin->menuList->user['menuOrder']['10'] = 'user';
|
||||
$lang->admin->menuList->user['menuOrder']['15'] = 'group';
|
||||
$lang->admin->menuList->company['menuOrder']['5'] = 'dept';
|
||||
$lang->admin->menuList->company['menuOrder']['10'] = 'browseUser';
|
||||
$lang->admin->menuList->company['menuOrder']['15'] = 'group';
|
||||
|
||||
$lang->admin->menuList->model['subMenu']['common'] = array('link' => "{$lang->globalSetting}|custom|required|module=project", 'subModule' => 'custom,subject,holiday,stage', 'exclude' => 'stage-browse,stage-plusbrowse,stage-create,stage-edit,stage-batchcreate');
|
||||
$lang->admin->menuList->model['subMenu']['scrum'] = array('link' => "{$lang->scrumModel}|auditcl|scrumbrowse|", 'subModule' => 'auditcl');
|
||||
@@ -84,22 +84,23 @@ $lang->admin->menuList->model['menuOrder']['15'] = 'waterfall';
|
||||
$lang->admin->menuList->model['menuOrder']['20'] = 'agileplus';
|
||||
$lang->admin->menuList->model['menuOrder']['25'] = 'waterfallplus';
|
||||
|
||||
$lang->admin->menuList->model['tabMenu']['common']['project'] = array('link' => "{$lang->project->common}|custom|required|module=project", 'alias' => 'set', 'exclude' => 'custom', 'links' => array('custom|set|'));
|
||||
$lang->admin->menuList->model['tabMenu']['common']['stage'] = array('link' => "{$lang->stage->type}|stage|settype|", 'subModule' => 'stage', 'links' => array('stage|browse|'));
|
||||
$lang->admin->menuList->model['tabMenu']['common']['project'] = array('link' => "{$lang->project->common}|custom|required|module=project", 'alias' => 'set', 'exclude' => 'custom', 'links' => array('custom|set|module=project&field=unitList'));
|
||||
if(helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['common']['stage'] = array('link' => "{$lang->stage->type}|stage|settype|", 'subModule' => 'stage', 'links' => array('stage|browse|'));
|
||||
$lang->admin->menuList->model['tabMenu']['common']['build'] = array('link' => "{$lang->build->common}|custom|required|module=build", 'alias' => 'set', 'exclude' => 'custom');
|
||||
$lang->admin->menuList->model['tabMenu']['common']['flow'] = array('link' => "{$lang->custom->flow}|custom|flow|", 'divider' => true);
|
||||
$lang->admin->menuList->model['tabMenu']['common']['code'] = array('link' => "{$lang->code}|custom|code|");
|
||||
$lang->admin->menuList->model['tabMenu']['common']['hours'] = array('link' => "{$lang->workingHour}|custom|hours|", 'subModule' => 'holiday', 'links' => array('holiday|browse|'));
|
||||
$lang->admin->menuList->model['tabMenu']['waterfall']['stage'] = array('link' => "{$lang->stage->list}|stage|browse|", 'subModule' => 'stage', 'exclude' => 'stage-plusbrowse');
|
||||
$lang->admin->menuList->model['tabMenu']['waterfallplus']['stage'] = array('link' => "{$lang->stage->list}|stage|plusbrowse|", 'subModule' => 'stage', 'exclude' => 'stage-browse');
|
||||
$lang->admin->menuList->model['tabMenu']['common']['hours'] = array('link' => "{$lang->workingHour}|custom|hours|", 'subModule' => 'holiday', 'links' => array('holiday|browse|', 'custom|hours|'));
|
||||
if(helper::hasFeature('waterfall')) $lang->admin->menuList->model['tabMenu']['waterfall']['stage'] = array('link' => "{$lang->stage->list}|stage|browse|", 'subModule' => 'stage', 'exclude' => 'stage-plusbrowse');
|
||||
if(helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['waterfallplus']['stage'] = array('link' => "{$lang->stage->list}|stage|plusbrowse|", 'subModule' => 'stage', 'exclude' => 'stage-browse');
|
||||
|
||||
$lang->admin->menuList->model['tabMenu']['menuOrder']['common']['5'] = 'project';
|
||||
$lang->admin->menuList->model['tabMenu']['menuOrder']['common']['7'] = 'stage';
|
||||
if(helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['menuOrder']['common']['7'] = 'stage';
|
||||
$lang->admin->menuList->model['tabMenu']['menuOrder']['common']['10'] = 'build';
|
||||
$lang->admin->menuList->model['tabMenu']['menuOrder']['common']['35'] = 'flow';
|
||||
$lang->admin->menuList->model['tabMenu']['menuOrder']['common']['40'] = 'code';
|
||||
$lang->admin->menuList->model['tabMenu']['menuOrder']['common']['45'] = 'hours';
|
||||
$lang->admin->menuList->model['tabMenu']['menuOrder']['waterfall']['5'] = 'stage';
|
||||
$lang->admin->menuList->model['tabMenu']['menuOrder']['waterfallplus']['5'] = 'stage';
|
||||
if(helper::hasFeature('waterfall')) $lang->admin->menuList->model['tabMenu']['menuOrder']['waterfall']['5'] = 'stage';
|
||||
if(helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['menuOrder']['waterfallplus']['5'] = 'stage';
|
||||
|
||||
$lang->admin->menuList->feature['subMenu']['my'] = array('link' => "{$lang->my->common}|custom|set|module=todo&field=priList", 'exclude' => 'set,required');
|
||||
$lang->admin->menuList->feature['subMenu']['product'] = array('link' => "{$lang->productCommon}|custom|required|module=product", 'exclude' => 'set,required', 'alias' => 'browsestoryconcept,product');
|
||||
|
||||
@@ -66,7 +66,7 @@ $lang->admin->notice->ignore = "不再提示";
|
||||
$lang->admin->notice->int = "『%s』应当是正整数。";
|
||||
|
||||
$lang->admin->registerNotice = new stdclass();
|
||||
$lang->admin->registerNotice->common = '注册新帐号绑定';
|
||||
$lang->admin->registerNotice->common = '注册新帐号';
|
||||
$lang->admin->registerNotice->caption = '禅道社区登记';
|
||||
$lang->admin->registerNotice->click = '点击此处';
|
||||
$lang->admin->registerNotice->lblAccount = '请设置您的用户名,英文字母和数字的组合,三位以上。';
|
||||
@@ -186,6 +186,7 @@ $lang->admin->updateDynamics = '更新动态';
|
||||
$lang->admin->updatePatch = '补丁更新';
|
||||
$lang->admin->upgradeRecommend = '推荐升级';
|
||||
$lang->admin->zentaoUsed = '您已使用禅道';
|
||||
$lang->admin->noPriv = '您没有访问该区块的权限。';
|
||||
|
||||
$lang->admin->openTag = '禅道';
|
||||
$lang->admin->bizTag = '禅道企业版';
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<div class="settings-list <?php if($config->vision == 'lite') echo 'lite-setting';?>">
|
||||
<?php foreach($lang->admin->menuList as $menuKey => $menu):?>
|
||||
<?php if($config->vision == 'lite' and !in_array($menuKey, $config->admin->liteMenuList)) continue;?>
|
||||
<div class="setting-box">
|
||||
<div class="setting-box" <?php if($menu['disabled']) echo "title={$lang->admin->noPriv}";?> data-id="<?php echo $menuKey;?>">
|
||||
<button class="btn shadow-primary-hover" <?php if($menu['disabled']) echo 'disabled';?> data-link='<?php echo $menu['link'];?>'>
|
||||
<h4 class="flex align-center w-full">
|
||||
<div class="flex align-center">
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div class='col-md-6'>
|
||||
<div <?php if(common::hasPriv('admin', 'bind')) echo "class='col-md-6'";?>>
|
||||
<div class='panel'>
|
||||
<div class='panel-heading'><strong><?php echo $lang->admin->registerNotice->common?></strong></div>
|
||||
<form class='mw-600px' method="post" target="hiddenwin">
|
||||
@@ -94,6 +94,7 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php if(common::hasPriv('admin', 'bind')):?>
|
||||
<div class='col-md-6'>
|
||||
<div class='panel'>
|
||||
<div class='panel-heading'><strong><?php echo $lang->admin->registerNotice->bind?></strong></div>
|
||||
@@ -118,6 +119,7 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<script>
|
||||
$(function()
|
||||
|
||||
@@ -1504,7 +1504,7 @@ class block extends control
|
||||
$sprints = $this->dao->select('status, count(*) as sprints')->from(TABLE_EXECUTION)
|
||||
->where('deleted')->eq(0)
|
||||
->beginIF($this->config->vision == 'lite')->andWhere('type')->eq('kanban')->fi()
|
||||
->beginIF($this->config->vision == 'rnd')->andWhere('type')->eq('sprint')->fi()
|
||||
->beginIF($this->config->vision == 'rnd')->andWhere('type')->in('sprint,kanban')->fi()
|
||||
->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->sprints)->fi()
|
||||
->andWhere('project')->eq($this->session->project)
|
||||
->groupBy('status')
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
.block-guide .tab-pane .app-client .tree-menu li .avatar img {padding: 6px;}
|
||||
.block-guide .tab-pane .app-client .client-desc {padding-top: 12px;}
|
||||
.block-guide .tab-pane .app-client .client-desc img {height: 195px;}
|
||||
.block-guide .tab-pane .app-qrcode {padding: 10px 20px;}
|
||||
.block-guide .tab-pane .app-qrcode .col-md-12 {padding-left: 0; padding-top: 10px;}
|
||||
.block-guide .tab-pane .app-qrcode .qrcode-down img {padding-top: 16px;}
|
||||
.block-guide .tab-pane .app-qrcode .qrcode-down .text-primary {padding-top: 10px;}
|
||||
|
||||
@@ -112,6 +112,7 @@ class buildModel extends model
|
||||
$buildQuery = str_replace($field, "t1." . $field, $buildQuery);
|
||||
}
|
||||
}
|
||||
if(strpos($this->session->projectBuildQuery, 'execution') !== false) $buildQuery = str_replace('`execution`', 't2.`id`', $buildQuery);
|
||||
|
||||
return $this->getProjectBuilds($projectID, 'bysearch', $buildQuery);
|
||||
}
|
||||
|
||||
@@ -265,8 +265,8 @@ $lang->calendar = 'Calendar';
|
||||
|
||||
$lang->my->work = 'Work';
|
||||
|
||||
$lang->project->list = 'Project List';
|
||||
$lang->project->kanban = 'Project Kanban';
|
||||
$lang->project->list = $lang->projectCommon . ' List';
|
||||
$lang->project->kanban = $lang->projectCommon . ' Kanban';
|
||||
|
||||
$lang->execution->executionKanban = "{$lang->execution->common} Kanban";
|
||||
$lang->execution->all = "{$lang->execution->common} List";
|
||||
@@ -274,8 +274,8 @@ $lang->execution->all = "{$lang->execution->common} List";
|
||||
$lang->doc->recent = 'Recent';
|
||||
$lang->doc->my = 'My';
|
||||
$lang->doc->favorite = 'Favorite';
|
||||
$lang->doc->product = 'Product';
|
||||
$lang->doc->project = 'Project';
|
||||
$lang->doc->product = $lang->productCommon;
|
||||
$lang->doc->project = $lang->projectCommon;
|
||||
$lang->doc->api = 'API';
|
||||
$lang->doc->execution = $lang->execution->common;
|
||||
$lang->doc->custom = 'Custom';
|
||||
|
||||
@@ -265,8 +265,8 @@ $lang->calendar = 'Calendar';
|
||||
|
||||
$lang->my->work = 'Work';
|
||||
|
||||
$lang->project->list = 'Project List';
|
||||
$lang->project->kanban = 'Project Kanban';
|
||||
$lang->project->list = $lang->projectCommon . ' List';
|
||||
$lang->project->kanban = $lang->projectCommon . ' Kanban';
|
||||
|
||||
$lang->execution->executionKanban = "{$lang->execution->common} Kanban";
|
||||
$lang->execution->all = "{$lang->execution->common} List";
|
||||
@@ -274,8 +274,8 @@ $lang->execution->all = "{$lang->execution->common} List";
|
||||
$lang->doc->recent = 'Recent';
|
||||
$lang->doc->my = 'My';
|
||||
$lang->doc->favorite = 'Favorite';
|
||||
$lang->doc->product = 'Product';
|
||||
$lang->doc->project = 'Project';
|
||||
$lang->doc->product = $lang->productCommon;
|
||||
$lang->doc->project = $lang->projectCommon;
|
||||
$lang->doc->api = 'API';
|
||||
$lang->doc->execution = $lang->execution->common;
|
||||
$lang->doc->custom = 'Custom';
|
||||
|
||||
@@ -265,8 +265,8 @@ $lang->calendar = 'Calendar';
|
||||
|
||||
$lang->my->work = 'Work';
|
||||
|
||||
$lang->project->list = 'Project List';
|
||||
$lang->project->kanban = 'Project Kanban';
|
||||
$lang->project->list = $lang->projectCommon . ' List';
|
||||
$lang->project->kanban = $lang->projectCommon . ' Kanban';
|
||||
|
||||
$lang->execution->executionKanban = "{$lang->execution->common} Kanban";
|
||||
$lang->execution->all = "{$lang->execution->common} List";
|
||||
@@ -274,8 +274,8 @@ $lang->execution->all = "{$lang->execution->common} List";
|
||||
$lang->doc->recent = 'Recent';
|
||||
$lang->doc->my = 'My';
|
||||
$lang->doc->favorite = 'Favorite';
|
||||
$lang->doc->product = 'Product';
|
||||
$lang->doc->project = 'Project';
|
||||
$lang->doc->product = $lang->productCommon;
|
||||
$lang->doc->project = $lang->projectCommon;
|
||||
$lang->doc->api = 'API';
|
||||
$lang->doc->execution = $lang->execution->common;
|
||||
$lang->doc->custom = 'Custom';
|
||||
|
||||
@@ -137,8 +137,8 @@ $lang->program->homeMenu->browse = array('link' => "{$lang->program->list}|progr
|
||||
$lang->program->homeMenu->kanban = array('link' => "{$lang->program->kanban}|program|kanban|");
|
||||
|
||||
$lang->program->menu = new stdclass();
|
||||
$lang->program->menu->product = array('link' => "{$lang->product->common}|program|product|programID=%s", 'alias' => 'view');
|
||||
$lang->program->menu->project = array('link' => "{$lang->project->common}|program|project|programID=%s");
|
||||
$lang->program->menu->product = array('link' => "{$lang->productCommon}|program|product|programID=%s", 'alias' => 'view');
|
||||
$lang->program->menu->project = array('link' => "{$lang->projectCommon}|program|project|programID=%s");
|
||||
$lang->program->menu->personnel = array('link' => "{$lang->personnel->common}|personnel|invest|programID=%s");
|
||||
$lang->program->menu->stakeholder = array('link' => "{$lang->stakeholder->common}|program|stakeholder|programID=%s", 'alias' => 'createstakeholder');
|
||||
|
||||
@@ -163,7 +163,7 @@ $lang->product->menu = new stdclass();
|
||||
$lang->product->menu->dashboard = array('link' => "{$lang->dashboard}|product|dashboard|productID=%s");
|
||||
$lang->product->menu->story = array('link' => "$lang->SRCommon|product|browse|productID=%s", 'alias' => 'batchedit', 'subModule' => 'story');
|
||||
$lang->product->menu->plan = array('link' => "{$lang->productplan->shortCommon}|productplan|browse|productID=%s", 'subModule' => 'productplan,bug');
|
||||
$lang->product->menu->project = array('link' => "{$lang->project->common}|product|project|status=all&productID=%s");
|
||||
$lang->product->menu->project = array('link' => "{$lang->projectCommon}|product|project|status=all&productID=%s");
|
||||
$lang->product->menu->release = array('link' => "{$lang->release->common}|release|browse|productID=%s", 'subModule' => 'release');
|
||||
$lang->product->menu->roadmap = array('link' => "{$lang->roadmap}|product|roadmap|productID=%s");
|
||||
$lang->product->menu->requirement = array('link' => "{$lang->URCommon}|product|browse|productID=%s&branch=&browseType=unclosed¶m=0&storyType=requirement", 'alias' => 'batchedit', 'subModule' => 'story');
|
||||
@@ -234,8 +234,8 @@ $lang->scrum->menuOrder[25] = 'devops';
|
||||
$lang->scrum->menuOrder[30] = 'doc';
|
||||
$lang->scrum->menuOrder[35] = 'build';
|
||||
$lang->scrum->menuOrder[40] = 'release';
|
||||
$lang->scrum->menuOrder[48] = 'dynamic';
|
||||
$lang->scrum->menuOrder[50] = 'settings';
|
||||
$lang->scrum->menuOrder[45] = 'dynamic';
|
||||
$lang->scrum->menuOrder[55] = 'settings';
|
||||
|
||||
$lang->scrum->menu->doc['subMenu'] = new stdclass();
|
||||
|
||||
@@ -248,7 +248,7 @@ $lang->scrum->menu->qa['subMenu']->testreport = array('link' => "{$lang->testrep
|
||||
|
||||
$lang->scrum->menu->settings['subMenu'] = new stdclass();
|
||||
$lang->scrum->menu->settings['subMenu']->view = array('link' => "$lang->overview|project|view|project=%s", 'alias' => 'edit');
|
||||
$lang->scrum->menu->settings['subMenu']->products = array('link' => "{$lang->product->common}|project|manageProducts|project=%s", 'alias' => 'manageproducts');
|
||||
$lang->scrum->menu->settings['subMenu']->products = array('link' => "{$lang->productCommon}|project|manageProducts|project=%s", 'alias' => 'manageproducts');
|
||||
$lang->scrum->menu->settings['subMenu']->members = array('link' => "{$lang->team->common}|project|team|project=%s", 'alias' => 'managemembers,team');
|
||||
$lang->scrum->menu->settings['subMenu']->whitelist = array('link' => "{$lang->whitelist}|project|whitelist|project=%s", 'subModule' => 'personnel');
|
||||
$lang->scrum->menu->settings['subMenu']->stakeholder = array('link' => "{$lang->stakeholder->common}|stakeholder|browse|project=%s", 'subModule' => 'stakeholder');
|
||||
@@ -324,7 +324,7 @@ $lang->kanbanProject->menuOrder[15] = 'settings';
|
||||
|
||||
$lang->kanbanProject->menu->settings['subMenu'] = new stdclass();
|
||||
$lang->kanbanProject->menu->settings['subMenu']->view = array('link' => "$lang->overview|project|view|project=%s", 'alias' => 'edit');
|
||||
$lang->kanbanProject->menu->settings['subMenu']->products = array('link' => "{$lang->product->common}|project|manageProducts|project=%s", 'alias' => 'manageproducts');
|
||||
$lang->kanbanProject->menu->settings['subMenu']->products = array('link' => "{$lang->productCommon}|project|manageProducts|project=%s", 'alias' => 'manageproducts');
|
||||
$lang->kanbanProject->menu->settings['subMenu']->members = array('link' => "{$lang->team->common}|project|team|project=%s", 'alias' => 'managemembers,team');
|
||||
$lang->kanbanProject->menu->settings['subMenu']->whitelist = array('link' => "{$lang->whitelist}|project|whitelist|project=%s", 'subModule' => 'personnel');
|
||||
$lang->kanbanProject->menu->settings['subMenu']->module = array('link' => "{$lang->module}|tree|browse|product=%s&view=story");
|
||||
|
||||
@@ -265,8 +265,8 @@ $lang->calendar = '日程';
|
||||
|
||||
$lang->my->work = '待处理';
|
||||
|
||||
$lang->project->list = '项目列表';
|
||||
$lang->project->kanban = '项目看板';
|
||||
$lang->project->list = $lang->projectCommon . '列表';
|
||||
$lang->project->kanban = $lang->projectCommon . '看板';
|
||||
|
||||
$lang->execution->executionKanban = "{$lang->execution->common}看板";
|
||||
$lang->execution->all = "{$lang->execution->common}列表";
|
||||
@@ -274,8 +274,8 @@ $lang->execution->all = "{$lang->execution->common}列表";
|
||||
$lang->doc->recent = '最近文档';
|
||||
$lang->doc->my = '我的文档';
|
||||
$lang->doc->favorite = '我的收藏';
|
||||
$lang->doc->product = '产品库';
|
||||
$lang->doc->project = '项目库';
|
||||
$lang->doc->product = $lang->productCommon . '库';
|
||||
$lang->doc->project = $lang->projectCommon . '库';
|
||||
$lang->doc->api = '接口库';
|
||||
$lang->doc->execution = "{$lang->execution->common}库";
|
||||
$lang->doc->custom = '自定义库';
|
||||
|
||||
@@ -10,6 +10,7 @@ $lang->custom->key = 'Key';
|
||||
$lang->custom->value = 'Value';
|
||||
$lang->custom->working = 'WorkStyle';
|
||||
$lang->custom->select = 'Select Concept';
|
||||
$lang->custom->hours = 'Hours';
|
||||
$lang->custom->branch = 'Multi Branch';
|
||||
$lang->custom->owner = 'Owner';
|
||||
$lang->custom->module = 'Module';
|
||||
|
||||
@@ -10,6 +10,7 @@ $lang->custom->key = 'Key';
|
||||
$lang->custom->value = 'Value';
|
||||
$lang->custom->working = 'Mode';
|
||||
$lang->custom->select = 'Select Concept';
|
||||
$lang->custom->hours = 'Hours';
|
||||
$lang->custom->branch = 'Multi-Branch';
|
||||
$lang->custom->owner = 'Owner';
|
||||
$lang->custom->module = 'Module';
|
||||
|
||||
@@ -10,6 +10,7 @@ $lang->custom->key = 'Clé';
|
||||
$lang->custom->value = 'Valeur';
|
||||
$lang->custom->working = 'Mode';
|
||||
$lang->custom->select = 'Choix du Concept';
|
||||
$lang->custom->hours = 'Hours';
|
||||
$lang->custom->branch = 'Multi-Branches';
|
||||
$lang->custom->owner = 'Propriétaire';
|
||||
$lang->custom->module = 'Module';
|
||||
|
||||
@@ -9,6 +9,7 @@ $lang->custom->restore = '恢复默认';
|
||||
$lang->custom->key = '键';
|
||||
$lang->custom->value = '值';
|
||||
$lang->custom->working = '工作方式';
|
||||
$lang->custom->hours = '工时';
|
||||
$lang->custom->select = '请选择流程:';
|
||||
$lang->custom->branch = '多分支';
|
||||
$lang->custom->owner = '所有者';
|
||||
|
||||
@@ -995,14 +995,21 @@ class customModel extends model
|
||||
foreach($this->config->custom->dataFeatures as $feature)
|
||||
{
|
||||
$function = 'has' . ucfirst($feature) . 'Data';
|
||||
if(!$this->$function()) $disabledFeatures .= "$feature,";
|
||||
if(!$this->$function())
|
||||
{
|
||||
$disabledFeatures .= "$feature,";
|
||||
if(strpos($feature, 'scrum') === 0) $disabledFeatures .= 'agileplus' . substr($feature, 5) . ',';
|
||||
}
|
||||
}
|
||||
$disabledFeatures .= 'scrumMeasrecord,productTrack,productRoadmap';
|
||||
$disabledFeatures .= 'scrumMeasrecord,agileplusMeasrecord,productTrack,productRoadmap';
|
||||
}
|
||||
|
||||
$disabledFeatures = rtrim($disabledFeatures, ',');
|
||||
$this->loadModel('setting')->setItem('system.common.disabledFeatures', $disabledFeatures);
|
||||
|
||||
$URAndSR = strpos(",$disabledFeatures,", ',productUR,') === false ? 1 : 0;
|
||||
$this->setting->setItem('system.custom.URAndSR', $URAndSR);
|
||||
|
||||
$this->processMeasrecordCron();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<div class='nav list-group tab-menu'>
|
||||
<a href="#hoursContent" data-toggle="tab" class="hours <?php if($type == 'hours') echo 'active'?>"><?php echo $lang->custom->setHours;?></a>
|
||||
<a href="#weekendContent" data-toggle="tab" class="weekend <?php if($type == 'weekend') echo 'active'?>"><?php echo $lang->custom->setWeekend;?></a>
|
||||
<?php echo html::a($this->createLink('holiday', 'browse'), $lang->custom->setHoliday);?>
|
||||
<?php if(common::hasPriv('holiday', 'browse')) echo html::a($this->createLink('holiday', 'browse'), $lang->custom->setHoliday);?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -247,7 +247,6 @@ $config->dev->navTypes = array('second', 'third', 'tag');
|
||||
$config->disableFeature = array();
|
||||
if(!helper::hasFeature('waterfall')) $config->disableFeature = array('design', 'stage', 'programplan', 'weekly', 'researchplan', 'researchreport', 'gapanalysis');
|
||||
|
||||
$config->dev->disableMainMenu = array('project', 'product');
|
||||
$config->dev->projectMenus = array('project', 'scrum', 'waterfall', 'kanbanProject');
|
||||
$config->dev->hideMainMenu = array('admin', 'kanban');
|
||||
if($config->vision == 'lite')
|
||||
@@ -257,3 +256,6 @@ if($config->vision == 'lite')
|
||||
}
|
||||
|
||||
$config->dev->linkMethods['my']['my-calendar'] = array('my', 'todo');
|
||||
|
||||
$config->dev->skipMenus['first'] = array('project', 'product');
|
||||
$config->dev->skipMenus['second'] = array('menu_storyGroup', 'menu_story');
|
||||
|
||||
+51
-3
@@ -321,7 +321,10 @@ class devModel extends model
|
||||
|
||||
if(isset($defaultLang->$module->menu))
|
||||
{
|
||||
foreach($defaultLang->$module->menu as $menuKey => $menu)
|
||||
$menuList = $defaultLang->$module->menu;
|
||||
if(isset($defaultLang->$module->menuOrder)) $menuList->menuOrder = $defaultLang->$module->menuOrder;
|
||||
$menuList = $this->sortMenus($menuList);
|
||||
foreach($menuList as $menuKey => $menu)
|
||||
{
|
||||
if(is_array($menu) and !isset($menu['link'])) continue;
|
||||
|
||||
@@ -340,11 +343,34 @@ class devModel extends model
|
||||
else
|
||||
{
|
||||
$menus = ($type == 'third' and isset($defaultLang->$module->menu->{$method}['subMenu'])) ? $defaultLang->$module->menu->{$method}['subMenu'] : $defaultLang->mainNav;
|
||||
if(isset($defaultLang->$module->menu->{$method}['menuOrder'])) $menus->menuOrder = $defaultLang->$module->menu->{$method}['menuOrder'];
|
||||
$menus = $this->sortMenus($menus);
|
||||
}
|
||||
|
||||
return $menus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort menus.
|
||||
*
|
||||
* @param array|object $menus
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function sortMenus($menus)
|
||||
{
|
||||
if(!is_array($menus)) $menus = (array)$menus;
|
||||
if(!isset($menus['menuOrder'])) return $menus;
|
||||
$sortedMenus = array();
|
||||
$menuOrders = $menus['menuOrder'];
|
||||
ksort($menuOrders);
|
||||
foreach($menuOrders as $menuKey)
|
||||
{
|
||||
if(isset($menus[$menuKey])) $sortedMenus[$menuKey] = $menus[$menuKey];
|
||||
}
|
||||
return $sortedMenus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get original lang.
|
||||
*
|
||||
@@ -412,8 +438,12 @@ class devModel extends model
|
||||
$menus = $this->getLinkTitle($lang);
|
||||
foreach($menus as $linkKey => $menu)
|
||||
{
|
||||
if($type == 'first' and in_array($linkKey, $this->config->dev->disableMainMenu)) continue;
|
||||
foreach($this->config->dev->skipMenus as $menuType => $skipMenus)
|
||||
{
|
||||
if($type == $menuType and in_array($linkKey, $skipMenus)) continue 2;
|
||||
}
|
||||
|
||||
if($menu == '@branch@') $menu = $this->lang->dev->branch;
|
||||
$originalLangs[$langKey . $linkKey] = $menu;
|
||||
}
|
||||
}
|
||||
@@ -508,6 +538,10 @@ class devModel extends model
|
||||
*/
|
||||
public function loadDefaultLang($language = 'zh-cn', $module = 'common')
|
||||
{
|
||||
if(empty($language)) $language = 'zh-cn';
|
||||
if(empty($module)) $module = 'common';
|
||||
if($module != 'common' and !isset($this->defaultLang)) return null;
|
||||
|
||||
$clientLang = $this->app->clientLang;
|
||||
if($language and $language != $clientLang) $this->app->clientLang = $language;
|
||||
|
||||
@@ -573,6 +607,7 @@ class devModel extends model
|
||||
public function getThirdMenus($menu, $module = '', $method = '')
|
||||
{
|
||||
$menus = array();
|
||||
if($this->config->vision == 'lite' and $menu == 'project') $menu = 'kanbanProject';
|
||||
if(!isset($this->lang->$menu->menu)) return $menus;
|
||||
|
||||
$menuLang = $this->getLinkTitle($this->lang->$menu->menu);
|
||||
@@ -609,7 +644,14 @@ class devModel extends model
|
||||
foreach(array('homeMenu', 'menu') as $menu)
|
||||
{
|
||||
if(!isset($this->lang->$module->$menu)) continue;
|
||||
foreach($this->lang->$module->$menu as $menuKey => $menuValue)
|
||||
$menuList = $this->lang->$module->$menu;
|
||||
if($menu == 'menu' and isset($this->lang->$module->menuOrder))
|
||||
{
|
||||
$menuList->menuOrder = $this->lang->$module->menuOrder;
|
||||
$menuList = $this->sortMenus($menuList);
|
||||
}
|
||||
|
||||
foreach($menuList as $menuKey => $menuValue)
|
||||
{
|
||||
if(is_array($menuValue) and !isset($menuValue['link'])) continue;
|
||||
$link = is_array($menuValue) ? $menuValue['link'] : $menuValue;
|
||||
@@ -638,6 +680,11 @@ class devModel extends model
|
||||
foreach(array('subMenu', 'dropMenu') as $menu)
|
||||
{
|
||||
if(!isset($menuValue[$menu])) continue;
|
||||
if($menu == 'subMenu' and isset($menuValue['menuOrder']))
|
||||
{
|
||||
$menuValue[$menu]->menuOrder = $menuValue['menuOrder'];
|
||||
$menuValue[$menu] = $this->sortMenus($menuValue[$menu]);
|
||||
}
|
||||
foreach($menuValue[$menu] as $subMenuKey => $subMenuValue)
|
||||
{
|
||||
if(is_array($subMenuValue) and !isset($subMenuValue['link'])) continue;
|
||||
@@ -781,6 +828,7 @@ class devModel extends model
|
||||
public function getLinkTitle($menus)
|
||||
{
|
||||
$linksTitle = array();
|
||||
$menus = $this->sortMenus($menus);
|
||||
foreach($menus as $menuKey => $menu)
|
||||
{
|
||||
if(is_array($menu) and !isset($menu['link'])) continue;
|
||||
|
||||
@@ -472,6 +472,7 @@ class execution extends control
|
||||
$this->view->users = $users;
|
||||
$this->view->moduleID = 0;
|
||||
$this->view->moduleName = $this->lang->tree->all;
|
||||
$this->view->features = $this->execution->getExecutionFeatures($execution);
|
||||
$this->view->filter = $filter;
|
||||
$this->view->allCount = $allCount;
|
||||
$this->display();
|
||||
@@ -1548,6 +1549,7 @@ class execution extends control
|
||||
$this->view->executionName = $execution->name;
|
||||
$this->view->executionID = $executionID;
|
||||
$this->view->chartData = $chartData;
|
||||
$this->view->features = $this->execution->getExecutionFeatures($execution);
|
||||
$this->view->begin = $begin;
|
||||
$this->view->end = $end;
|
||||
$this->view->minDate = $minDate;
|
||||
@@ -1993,7 +1995,8 @@ class execution extends control
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
if($execution->type == 'stage') $this->loadModel('programplan')->computeProgress($executionID, 'edit');
|
||||
$project = $this->loadModel('project')->getById($execution->project);
|
||||
if($project->model == 'waterfall' or $project->model == 'waterfallplus') $this->loadModel('programplan')->computeProgress($executionID, 'edit');
|
||||
|
||||
/* Link the plan stories. */
|
||||
$oldPlans = explode(',', implode(',' ,$oldPlans));
|
||||
@@ -2099,6 +2102,7 @@ class execution extends control
|
||||
{
|
||||
$productID = $this->product->getProductIDByProject($executionID);
|
||||
$parentStageList = $this->loadModel('programplan')->getParentStageList($execution->project, $executionID, $productID);
|
||||
unset($parentStageList[0]);
|
||||
}
|
||||
|
||||
$this->view->title = $title;
|
||||
@@ -2289,7 +2293,8 @@ class execution extends control
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
if($execution->type == 'stage') $this->loadModel('programplan')->computeProgress($executionID, 'start');
|
||||
$project = $this->loadModel('project')->getById($execution->project);
|
||||
if($project->model == 'waterfall' or $project->model == 'waterfallplus') $this->loadModel('programplan')->computeProgress($executionID, 'start');
|
||||
|
||||
$this->loadModel('common')->syncPPEStatus($executionID);
|
||||
$this->executeHooks($executionID);
|
||||
@@ -2381,7 +2386,8 @@ class execution extends control
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
if($execution->type == 'stage') $this->loadModel('programplan')->computeProgress($executionID, 'suspend');
|
||||
$project = $this->loadModel('project')->getById($execution->project);
|
||||
if($project->model == 'waterfall' or $project->model == 'waterfallplus') $this->loadModel('programplan')->computeProgress($executionID, 'suspend');
|
||||
|
||||
$this->executeHooks($executionID);
|
||||
if(isonlybody() and $from == 'kanban')
|
||||
@@ -2421,7 +2427,8 @@ class execution extends control
|
||||
$this->execution->activate($executionID);
|
||||
if(dao::isError()) return print(js::error(dao::getError()));
|
||||
|
||||
if($execution->type == 'stage') $this->loadModel('programplan')->computeProgress($executionID, 'activate');
|
||||
$project = $this->loadModel('project')->getById($execution->project);
|
||||
if($project->model == 'waterfall' or $project->model == 'waterfallplus') $this->loadModel('programplan')->computeProgress($executionID, 'activate');
|
||||
|
||||
$this->executeHooks($executionID);
|
||||
if(isonlybody() and $from == 'kanban')
|
||||
@@ -2469,7 +2476,8 @@ class execution extends control
|
||||
$this->execution->close($executionID);
|
||||
if(dao::isError()) return print(js::error(dao::getError()));
|
||||
|
||||
if($execution->type == 'stage') $this->loadModel('programplan')->computeProgress($executionID, 'close');
|
||||
$project = $this->loadModel('project')->getById($execution->project);
|
||||
if($project->model == 'waterfall' or $project->model == 'waterfallplus') $this->loadModel('programplan')->computeProgress($executionID, 'close');
|
||||
|
||||
$this->executeHooks($executionID);
|
||||
if(isonlybody() and $from == 'kanban')
|
||||
@@ -2590,6 +2598,7 @@ class execution extends control
|
||||
$this->view->chartData = $chartData;
|
||||
$this->view->canBeChanged = common::canModify('execution', $execution); // Determines whether an object is editable.
|
||||
$this->view->type = $type;
|
||||
$this->view->features = $this->execution->getExecutionFeatures($execution);
|
||||
$this->view->project = $this->loadModel('project')->getByID($execution->project);
|
||||
|
||||
$this->display();
|
||||
@@ -2951,6 +2960,7 @@ class execution extends control
|
||||
$this->view->executionID = $executionID;
|
||||
$this->view->level = $type;
|
||||
$this->view->tree = $this->execution->printTree($tree, $project->hasProduct);
|
||||
$this->view->features = $this->execution->getExecutionFeatures($execution);
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -3161,7 +3171,8 @@ class execution extends control
|
||||
$this->execution->updateUserView($executionID);
|
||||
$this->loadModel('common')->syncPPEStatus($executionID);
|
||||
|
||||
if($execution->type == 'stage') $this->loadModel('programplan')->computeProgress($executionID);
|
||||
$project = $this->loadModel('project')->getById($execution->project);
|
||||
if($project->model == 'waterfall' or $project->model == 'waterfallplus') $this->loadModel('programplan')->computeProgress($executionID);
|
||||
|
||||
$this->session->set('execution', '');
|
||||
$message = $this->executeHooks($executionID);
|
||||
|
||||
@@ -153,6 +153,7 @@ $lang->execution->daysGreaterProject = 'Days cannot be greater than days of exec
|
||||
$lang->execution->errorHours = 'Hours/Day cannot be greater than『24』';
|
||||
$lang->execution->agileplusMethodTip = 'When creating executions in an Agile Plus project, both Iteration and Kanban management methods are supported.';
|
||||
$lang->execution->typeTip = "The sub-stages of other types can be created under the parent stage of the 'mix' type, while the type of other parent-child levels is consistent.";
|
||||
$lang->execution->waterfallTip = 'In the Waterfall project or in the Waterfall + project,';
|
||||
|
||||
$lang->execution->start = 'Start';
|
||||
$lang->execution->activate = 'Aktivieren';
|
||||
|
||||
@@ -153,6 +153,7 @@ $lang->execution->daysGreaterProject = 'Days cannot be greater than days of exec
|
||||
$lang->execution->errorHours = 'Hours/Day cannot be greater than『24』';
|
||||
$lang->execution->agileplusMethodTip = 'When creating executions in an Agile Plus project, both Iteration and Kanban management methods are supported.';
|
||||
$lang->execution->typeTip = "The sub-stages of other types can be created under the parent stage of the 'mix' type, while the type of other parent-child levels is consistent.";
|
||||
$lang->execution->waterfallTip = 'In the Waterfall project or in the Waterfall + project,';
|
||||
|
||||
$lang->execution->start = 'Start';
|
||||
$lang->execution->activate = 'Activate';
|
||||
|
||||
@@ -153,6 +153,7 @@ $lang->execution->daysGreaterProject = 'Days cannot be greater than days of exec
|
||||
$lang->execution->errorHours = 'Hours/Day cannot be greater than『24』';
|
||||
$lang->execution->agileplusMethodTip = 'When creating executions in an Agile Plus project, both Iteration and Kanban management methods are supported.';
|
||||
$lang->execution->typeTip = "The sub-stages of other types can be created under the parent stage of the 'mix' type, while the type of other parent-child levels is consistent.";
|
||||
$lang->execution->waterfallTip = 'In the Waterfall project or in the Waterfall + project,';
|
||||
|
||||
$lang->execution->start = 'Démarrer';
|
||||
$lang->execution->activate = 'Activer';
|
||||
|
||||
@@ -148,11 +148,12 @@ $lang->execution->estimate = '预计';
|
||||
$lang->execution->consumed = '消耗';
|
||||
$lang->execution->left = '剩余';
|
||||
|
||||
$lang->execution->copyTeamTip = "可以选择复制项目或{$lang->execution->common}团队的成员";
|
||||
$lang->execution->daysGreaterProject = '可用工日不能大于执行的可用工日『%s』';
|
||||
$lang->execution->errorHours = '可用工时/天不能大于『24』';
|
||||
$lang->execution->agileplusMethodTip = '融合敏捷项目创建执行时,支持迭代和看板两种管理方法。';
|
||||
$lang->execution->typeTip = '“综合”类型的父阶段可以创建其它类型的子级,其它父子层级的类型均一致。';
|
||||
$lang->execution->copyTeamTip = "可以选择复制项目或{$lang->execution->common}团队的成员";
|
||||
$lang->execution->daysGreaterProject = '可用工日不能大于执行的可用工日『%s』';
|
||||
$lang->execution->errorHours = '可用工时/天不能大于『24』';
|
||||
$lang->execution->agileplusMethodTip = '融合敏捷项目创建执行时,支持迭代和看板两种管理方法。';
|
||||
$lang->execution->typeTip = '“综合”类型的父阶段可以创建其它类型的子级,其它父子层级的类型均一致。';
|
||||
$lang->execution->waterfallTip = '瀑布项目和融合瀑布项目中,';
|
||||
|
||||
$lang->execution->start = "开始";
|
||||
$lang->execution->activate = "激活";
|
||||
|
||||
@@ -153,6 +153,7 @@ class executionModel extends model
|
||||
if(!$features['build']) unset($this->lang->execution->menu->build);
|
||||
if(!$features['burn']) unset($this->lang->execution->menu->burn);
|
||||
if(!$features['other']) unset($this->lang->execution->menu->other);
|
||||
if(!$features['story'] and $this->config->edition == 'open') unset($this->lang->execution->menu->view);
|
||||
|
||||
if($executions and (!isset($executions[$executionID]) or !$this->checkPriv($executionID))) $this->accessDenied();
|
||||
|
||||
@@ -383,7 +384,7 @@ class executionModel extends model
|
||||
$type = 'sprint';
|
||||
if($project) $type = zget($this->config->execution->modelList, $project->model, 'sprint');
|
||||
|
||||
if($project->model == 'waterfall')
|
||||
if($project->model == 'waterfall' or $project->model == 'waterfallplus')
|
||||
{
|
||||
$this->checkWorkload('create', $_POST['percent'], $project);
|
||||
if(dao::isError()) return false;
|
||||
@@ -658,6 +659,8 @@ class executionModel extends model
|
||||
|
||||
if(dao::isError()) return false;
|
||||
|
||||
if(isset($_POST['parent'])) $this->loadModel('programplan')->setTreePath($executionID);
|
||||
|
||||
/* Get team and language item. */
|
||||
$this->loadModel('user');
|
||||
$team = $this->user->getTeamMemberPairs($executionID, 'execution');
|
||||
@@ -1567,7 +1570,7 @@ class executionModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
if($type == 'update' and $oldExecution->grade == 2)
|
||||
if($type == 'update' and $oldExecution->grade > 1)
|
||||
{
|
||||
$parentPlan = $this->loadModel('programPlan')->getByID($oldExecution->parent);
|
||||
$childrenTotalPercent = $this->dao->select('SUM(percent) as total')->from(TABLE_EXECUTION)->where('parent')->eq($oldExecution->parent)->andWhere('deleted')->eq(0)->fetch('total');
|
||||
@@ -1575,7 +1578,7 @@ class executionModel extends model
|
||||
|
||||
if($childrenTotalPercent > 100)
|
||||
{
|
||||
dao::$errors['parent'] = sprintf($this->lang->execution->workloadTotal, '%', $childrenTotalPercent . '%');
|
||||
dao::$errors['percent'] = sprintf($this->lang->execution->workloadTotal, '%', $childrenTotalPercent . '%');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1957,7 +1960,7 @@ class executionModel extends model
|
||||
->andWhere('t1.reviewStatus')->eq('doing')
|
||||
->fi()
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->page($pager, 't1.id')
|
||||
->fetchAll('id');
|
||||
|
||||
if(empty($productID) and !empty($executions)) $projectProductIdList = $this->dao->select('project, product')->from(TABLE_PROJECTPRODUCT)->where('project')->in(array_keys($executions))->fetchPairs();
|
||||
@@ -2124,7 +2127,10 @@ class executionModel extends model
|
||||
|
||||
$executionName = '';
|
||||
$paths = array_slice(explode(',', trim($execution->path, ',')), 1);
|
||||
foreach($paths as $path) $executionName .= '/' . $allExecutions[$path]->name;
|
||||
foreach($paths as $path)
|
||||
{
|
||||
if(isset($allExecutions[$path])) $executionName .= '/' . $allExecutions[$path]->name;
|
||||
}
|
||||
|
||||
if($executionName) $execution->name = ltrim($executionName, '/');
|
||||
if(isset($executionProducts[$id])) $execution->name = $executionProducts[$id] . '/' . $execution->name;
|
||||
@@ -2931,14 +2937,17 @@ class executionModel extends model
|
||||
$this->loadModel('task');
|
||||
|
||||
$taskStories = array();
|
||||
$parents = array();
|
||||
$execution = $this->getByID($executionID);
|
||||
$tasks = $this->dao->select('id,execution,assignedTo,story,consumed,status')->from(TABLE_TASK)->where('id')->in($this->post->tasks)->fetchAll('id');
|
||||
$tasks = $this->dao->select('id,execution,assignedTo,story,consumed,status,parent')->from(TABLE_TASK)->where('id')->in($this->post->tasks)->fetchAll('id');
|
||||
foreach($tasks as $task)
|
||||
{
|
||||
/* Save the assignedToes and stories, should linked to execution. */
|
||||
$assignedToes[$task->assignedTo] = $task->execution;
|
||||
$taskStories[$task->story] = $task->story;
|
||||
|
||||
if($task->parent < 0) $parents[$task->id] = $task->id;
|
||||
|
||||
$data = new stdclass();
|
||||
$data->project = $execution->project;
|
||||
$data->execution = $executionID;
|
||||
@@ -2958,6 +2967,10 @@ class executionModel extends model
|
||||
$this->loadModel('action')->create('task', $task->id, 'moved', '', $task->execution);
|
||||
}
|
||||
|
||||
/* Get stories of children task. */
|
||||
$childrens = $this->dao->select('*')->from(TABLE_TASK)->where('parent')->in($parents)->fetchAll('id');
|
||||
foreach($childrens as $children) $taskStories[$children->story] = $children->story;
|
||||
|
||||
/* Remove empty story. */
|
||||
unset($taskStories[0]);
|
||||
|
||||
@@ -5274,11 +5287,13 @@ class executionModel extends model
|
||||
$class = !empty($execution->children) ? 'disabled' : '';
|
||||
common::printIcon('task', 'create', "executionID={$execution->id}", '', 'list', '', '', $class, false, "data-app='execution'");
|
||||
|
||||
if($execution->type == 'stage')
|
||||
$project = $this->loadModel('project')->getByID($execution->project);
|
||||
if($execution->type == 'stage' or ($this->app->tab == 'project' and !empty($project->model) and $project->model == 'waterfallplus'))
|
||||
{
|
||||
$isCreateTask = $this->loadModel('programplan')->isCreateTask($execution->id);
|
||||
$disabled = ($isCreateTask and $execution->type == 'stage') ? '' : ' disabled';
|
||||
$title = !$isCreateTask ? $this->lang->programplan->error->createdTask : $this->lang->programplan->createSubPlan;
|
||||
$title = (!empty($disabled) and $execution->type != 'stage') ? $this->lang->programplan->error->notStage : $title;
|
||||
common::printIcon('programplan', 'create', "program={$execution->project}&productID=$productID&planID=$execution->id", $execution, 'list', 'split', '', $disabled, '', '', $title);
|
||||
}
|
||||
|
||||
@@ -5710,7 +5725,7 @@ class executionModel extends model
|
||||
{
|
||||
$label = $execution->type == 'stage' ? 'label-warning' : 'label-info';
|
||||
$link = $execution->type == 'kanban' ? helper::createLink('execution', 'kanban', "id=$execution->id") : helper::createLink('execution', 'task', "id=$execution->id");
|
||||
$execution->name = "<span class='project-type-label label label-outline $label'>{$this->lang->execution->typeList[$execution->type]}</span> " . html::a($link, $execution->name);
|
||||
$execution->name = "<span class='project-type-label label label-outline $label'>{$this->lang->execution->typeList[$execution->type]}</span> " . (empty($execution->children) ? html::a($link, $execution->name) : $execution->name);
|
||||
$execution->project = $execution->projectName;
|
||||
$execution->parent = ($execution->parent and $execution->grade > 1) ? $execution->parent : '';
|
||||
$execution->asParent = !empty($execution->children);
|
||||
|
||||
@@ -64,7 +64,10 @@
|
||||
<th class='c-user<?php echo zget($visibleFields, 'RD', ' hidden') . zget($requiredFields, 'RD', '', ' required');?>'><?php echo $lang->execution->RD;?></th>
|
||||
<th class='c-type<?php echo zget($visibleFields, 'type', ' hidden') . zget($requiredFields, 'type', '', ' required');?>'>
|
||||
<?php echo $lang->execution->$type;?>
|
||||
<icon class='icon icon-help' data-toggle='popover' data-trigger='focus hover' data-placement='right' data-tip-class='text-muted popover-sm' data-content="<?php echo $lang->execution->typeTip;?>"></icon>
|
||||
<?php if($this->app->tab == 'execution' or (isset($project) and ($project->model == 'waterfall' or $project->model == 'waterfallplus'))):?>
|
||||
<?php $typeTip = $this->app->tab == 'execution' ? $lang->execution->waterfallTip . lcfirst($lang->execution->typeTip) : $lang->execution->typeTip;?>
|
||||
<icon class='icon icon-help' data-toggle='popover' data-trigger='focus hover' data-placement='right' data-tip-class='text-muted popover-sm' data-content="<?php echo $typeTip;?>"></icon>
|
||||
<?php endif;?>
|
||||
</th>
|
||||
<th class='c-date required'><?php echo $lang->execution->begin;?></th>
|
||||
<th class='c-date required'><?php echo $lang->execution->end;?></th>
|
||||
|
||||
@@ -33,11 +33,11 @@
|
||||
$weekend = $withWeekend == 'true' ? 'noweekend' : 'withweekend';
|
||||
echo html::a('#', $lang->execution->$weekend, '', "class='btn btn-link' id='weekend'");
|
||||
?>
|
||||
<?php if($execution->lifetime != 'ops' and !in_array($execution->attribute, array('request', 'review'))):?>
|
||||
<?php if(!$features['story']) unset($lang->execution->cfdTypeList['story']);?>
|
||||
<?php if(!$features['qa']) unset($lang->execution->cfdTypeList['bug']);?>
|
||||
<div class='input-control w-140px'>
|
||||
<?php echo html::select('type', $lang->execution->cfdTypeList, $type, "class='form-control chosen'");?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<div id="cfdDateSelect">
|
||||
<form method='post' class='form-ajax not-watch'>
|
||||
<div class='input-group'>
|
||||
|
||||
@@ -166,7 +166,8 @@
|
||||
<div class='input-group required'>
|
||||
<span class='input-group-addon fix-border'><?php echo $lang->project->branch;?></span>
|
||||
<?php $branchIdList = isset($product->branches) ? join(',', $product->branches) : '';?>
|
||||
<?php echo html::select("branch[$i][]", isset($branchGroups[$product->id]) ? $branchGroups[$product->id] : array(), $branchIdList, "class='form-control chosen' multiple onchange=\"loadPlans('#products{$i}', this)\"");?>
|
||||
<?php if(!isset($linkedBranches)) echo html::select("branch[$i][]", isset($branchGroups[$product->id]) ? $branchGroups[$product->id] : array(), $branchIdList, "class='form-control chosen' multiple onchange=\"loadPlans('#products{$i}', this)\"");?>
|
||||
<?php if(isset($linkedBranches)) echo html::select("branch[$i][]", isset($branchGroups[$product->id]) ? $branchGroups[$product->id] : array(), !empty($linkedBranches[$product->id]) ? $linkedBranches[$product->id] : array(), "class='form-control chosen' multiple onchange=\"loadPlans('#products{$i}', this)\"");?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -174,7 +175,8 @@
|
||||
<div class="col-sm-6 planBox">
|
||||
<div class='input-group' <?php echo "id='plan$i'";?>>
|
||||
<span class='input-group-addon'><?php echo $lang->product->plan;?></span>
|
||||
<?php echo html::select("plans[$product->id][]", isset($productPlans[$product->id]) ? $productPlans[$product->id] : array(), isset($product->plans) ? $product->plans : '', "class='form-control chosen' multiple");?>
|
||||
<?php if(empty($productID) or (!empty($productID) and $productID != $product->id)) echo html::select("plans[$product->id][]", isset($productPlans[$product->id]) ? $productPlans[$product->id] : array(), isset($product->plans) ? $product->plans : '', "class='form-control chosen' multiple");?>
|
||||
<?php if(!empty($productID) and $productID == $product->id) echo html::select("plans[$product->id][]", !empty($productPlan) ? $productPlan : array(), isset($productPlan[$plan->id]) ? $plan->id : '', "class='form-control chosen' multiple");?>
|
||||
<?php if(!($isStage and !$project->division)):?>
|
||||
<div class='input-group-btn'>
|
||||
<a href='javascript:;' onclick='addNewLine(this)' class='btn btn-link addLine'><i class='icon-plus'></i></a>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
</tr>
|
||||
<?php elseif($app->tab == 'project' and $project->model == 'waterfallplus'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->programplan->parent;?></th>
|
||||
<th class='c-name'><?php echo $lang->programplan->parent;?></th>
|
||||
<td><?php echo html::select('parent', $parentStageList, $execution->parent, "class='form-control chosen '");?></td><td></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
$link = common::hasPriv('execution', 'importTask') ? $this->createLink('execution', 'importTask', "execution=$execution->id") : '#';
|
||||
echo "<li $class>" . html::a($link, $lang->execution->importTask, '', $misc) . "</li>";
|
||||
|
||||
if(isset($this->lang->execution->menu->qa))
|
||||
if($features['qa'])
|
||||
{
|
||||
$class = common::hasPriv('execution', 'importBug') ? '' : "class=disabled";
|
||||
$misc = common::hasPriv('execution', 'importBug') ? "class='import'" : "class=disabled";
|
||||
|
||||
@@ -44,7 +44,9 @@
|
||||
<th class='c-hour'><?php echo $lang->task->leftAB;?></th>
|
||||
<th class='c-date text-center'><?php echo $lang->task->deadlineAB;?></th>
|
||||
<th class='c-status'><?php echo $lang->statusAB;?></th>
|
||||
<?php if($execution->lifetime != 'ops' and !in_array($execution->attribute, array('request', 'review'))):?>
|
||||
<th class='c-story'><?php echo $lang->task->story;?></th>
|
||||
<?php endif;?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -65,6 +67,7 @@
|
||||
<td title="<?php echo $task->left . ' ' . $lang->execution->workHour;?>"><?php echo $task->left . ' ' . $lang->execution->workHourUnit;?></td>
|
||||
<td class="text-center <?php if(isset($task->delay)) echo 'delayed';?>"><?php if(substr($task->deadline, 0, 4) > 0) echo '<span>' . $task->deadline . '</span>';?></td>
|
||||
<td><span class='status-task status-<?php echo $task->status;?>'><?php echo $this->processStatus('task', $task);?></span></td>
|
||||
<?php if($execution->lifetime != 'ops' and !in_array($execution->attribute, array('request', 'review'))):?>
|
||||
<td class='text-left text-ellipsis' title="<?php echo $task->storyTitle;?>">
|
||||
<?php
|
||||
if($task->storyID)
|
||||
@@ -80,6 +83,7 @@
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<?php endif;?>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
|
||||
@@ -41,9 +41,12 @@
|
||||
$link = common::hasPriv('execution', 'importTask') ? $this->createLink('execution', 'importTask', "execution=$execution->id") : '#';
|
||||
echo "<li $misc>" . html::a($link, $lang->execution->importTask, '', $misc) . "</li>";
|
||||
|
||||
$misc = common::hasPriv('execution', 'importBug') ? '' : "class=disabled";
|
||||
$link = common::hasPriv('execution', 'importBug') ? $this->createLink('execution', 'importBug', "execution=$execution->id") : '#';
|
||||
echo "<li $misc>" . html::a($link, $lang->execution->importBug, '', $misc) . "</li>";
|
||||
if($features['qa'])
|
||||
{
|
||||
$misc = common::hasPriv('execution', 'importBug') ? '' : "class=disabled";
|
||||
$link = common::hasPriv('execution', 'importBug') ? $this->createLink('execution', 'importBug', "execution=$execution->id") : '#';
|
||||
echo "<li $misc>" . html::a($link, $lang->execution->importBug, '', $misc) . "</li>";
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -420,14 +420,13 @@
|
||||
<table class="table table-data data-basic">
|
||||
<tbody>
|
||||
<tr>
|
||||
<?php if($execution->lifetime == 'ops' or in_array($execution->attribute, array('request', 'review'))):?>
|
||||
<th><?php echo $lang->task->common;?></th>
|
||||
<td><?php echo $statData->taskCount;?></td>
|
||||
<?php else:?>
|
||||
<?php if($features['story']):?>
|
||||
<th><?php echo $lang->story->common;?></th>
|
||||
<td><?php echo $statData->storyCount;?></td>
|
||||
<?php endif;?>
|
||||
<th><?php echo $lang->task->common;?></th>
|
||||
<td><?php echo $statData->taskCount;?></td>
|
||||
<?php if($features['qa']):?>
|
||||
<th><?php echo $lang->bug->common;?></th>
|
||||
<td><?php echo $statData->bugCount;?></td>
|
||||
<?php endif;?>
|
||||
|
||||
@@ -236,7 +236,7 @@ class group extends control
|
||||
}
|
||||
|
||||
$this->lang->custom->common = $this->lang->group->config;
|
||||
if($this->config->edition == 'max' and $this->config->vision == 'rnd' and (!$menu or $menu == 'admin')) $this->lang->baseline->common = $this->lang->group->docTemplate;
|
||||
if($this->config->edition == 'max' and $this->config->vision == 'rnd' and isset($this->lang->baseline)) $this->lang->baseline->common = $this->lang->group->docTemplate;
|
||||
|
||||
$this->view->group = $group;
|
||||
$this->view->changelogs = ',' . join(',', $changelog) . ',';
|
||||
|
||||
@@ -1445,6 +1445,7 @@ $lang->resource->custom->setDefaultConcept = 'setDefaultConcept';
|
||||
$lang->resource->custom->deleteStoryConcept = 'deleteStoryConcept';
|
||||
$lang->resource->custom->kanban = 'kanban';
|
||||
$lang->resource->custom->code = 'code';
|
||||
$lang->resource->custom->hours = 'hours';
|
||||
|
||||
$lang->custom->methodOrder[5] = 'index';
|
||||
$lang->custom->methodOrder[10] = 'set';
|
||||
@@ -1462,6 +1463,7 @@ $lang->custom->methodOrder[65] = 'setDefaultConcept';
|
||||
$lang->custom->methodOrder[70] = 'deleteStoryConcept';
|
||||
$lang->custom->methodOrder[75] = 'kanban';
|
||||
$lang->custom->methodOrder[80] = 'code';
|
||||
$lang->custom->methodOrder[85] = 'hours';
|
||||
|
||||
$lang->resource->datatable = new stdclass();
|
||||
$lang->resource->datatable->setGlobal = 'setGlobal';
|
||||
|
||||
@@ -7,3 +7,5 @@
|
||||
.table-import {padding: 6px 5px 5px 5px; }
|
||||
.shadow-sm {box-shadow: 0 1px 1px rgb(0 0 0 / 5%), 0 2px 6px 0 rgb(0 0 0 / 25%)}
|
||||
.flex-center {display: flex; align-items: center; justify-content: center;}
|
||||
.c-desc {width: 280px;}
|
||||
p.c-desc {white-space: nowrap; margin-bottom: 0; text-overflow: clip; overflow: hidden;}
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
<div class='side-col' id='sidebar'>
|
||||
<div class='cell'>
|
||||
<div class='nav list-group tab-menu'>
|
||||
<?php if(common::hasPriv('custom', 'hours')):?>
|
||||
<a href="<?php echo $this->createLink('custom', 'hours', 'type=hours')?>"><?php echo $lang->custom->setHours;?></a>
|
||||
<a href="<?php echo $this->createLink('custom', 'hours', 'type=weekend')?>"><?php echo $lang->custom->setWeekend;?></a>
|
||||
<?php endif;?>
|
||||
<?php echo html::a($this->createLink('holiday', 'browse'), $lang->custom->setHoliday, '', "class='active'");?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -34,12 +36,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<table class='table has-sort-head'>
|
||||
<thead class="shadow-sm">
|
||||
<thead <?php if(empty($holidays)) echo 'class="shadow-sm"';?>>
|
||||
<tr>
|
||||
<th class='c-name'><?php echo $lang->holiday->name;?></th>
|
||||
<th class='c-time-limit'><?php echo $lang->holiday->holiday;?></th>
|
||||
<th class='c-status'><?php echo $lang->holiday->type;?></th>
|
||||
<th class='c-object'><?php echo $lang->holiday->desc;?></th>
|
||||
<th class='c-desc'><?php echo $lang->holiday->desc;?></th>
|
||||
<th class='c-actions-2'><?php echo $lang->actions;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -49,7 +51,7 @@
|
||||
<td><?php echo $holiday->name;?></td>
|
||||
<td><?php echo formatTime($holiday->begin, DT_DATE1) . ' ~ ' . formatTime($holiday->end, DT_DATE1);?></td>
|
||||
<td><?php echo zget($lang->holiday->typeList, $holiday->type);?></td>
|
||||
<td><?php echo $holiday->desc;?></td>
|
||||
<td><p class='c-desc'><?php echo $holiday->desc;?></p></td>
|
||||
<td class=" c-actions">
|
||||
<?php common::printIcon('holiday', 'edit', "id=$holiday->id", $holiday, 'list', '', '', 'iframe', 'yes');?>
|
||||
<?php common::printIcon('holiday', 'delete', "id=$holiday->id", $holiday, 'list', '', 'hiddenwin');?>
|
||||
|
||||
@@ -472,7 +472,6 @@ function renderExecutionItem(item, $item)
|
||||
].join('')).appendTo($item);
|
||||
|
||||
var $titleBox = $header.children('.executionName');
|
||||
debugger
|
||||
if(!$titleBox.length) $titleBox = $(
|
||||
[
|
||||
'<div class="executionName">',
|
||||
|
||||
@@ -200,7 +200,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.2'][] = array('title' => 'Agile Plus and Waterfall Plus management models are newly added. Support for unlimited splitting of waterfall project stages. The UI of Admin is completely upgraded and redesigned.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.2'][] = array('title' => 'Agile Plus and Waterfall Plus management models are newly added. Support for unlimited splitting of waterfall project stages. The UI of Admin is completely upgraded and redesigned. Fix bugs.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.1'][] = array('title' => 'The automation testing solution interaction is optimized, while a new snapshot management function is newly added. ZenTao IM implemented online collaboration of PPT documents.Fix bugs.', 'desc' => '');
|
||||
$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' => '');
|
||||
|
||||
@@ -200,7 +200,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.2'][] = array('title' => 'Agile Plus and Waterfall Plus management models are newly added. Support for unlimited splitting of waterfall project stages. The UI of Admin is completely upgraded and redesigned.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.2'][] = array('title' => 'Agile Plus and Waterfall Plus management models are newly added. Support for unlimited splitting of waterfall project stages. The UI of Admin is completely upgraded and redesigned. Fix bugs.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.1'][] = array('title' => 'The automation testing solution interaction is optimized, while a new snapshot management function is newly added. ZenTao IM implemented online collaboration of PPT documents.Fix bugs.', 'desc' => '');
|
||||
$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' => '');
|
||||
|
||||
@@ -200,7 +200,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.2'][] = array('title' => 'Agile Plus and Waterfall Plus management models are newly added. Support for unlimited splitting of waterfall project stages. The UI of Admin is completely upgraded and redesigned.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.2'][] = array('title' => 'Agile Plus and Waterfall Plus management models are newly added. Support for unlimited splitting of waterfall project stages. The UI of Admin is completely upgraded and redesigned. Fix bugs.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.1'][] = array('title' => 'The automation testing solution interaction is optimized, while a new snapshot management function is newly added. ZenTao IM implemented online collaboration of PPT documents.Fix bugs.', 'desc' => '');
|
||||
$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' => '');
|
||||
|
||||
@@ -200,7 +200,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.2'][] = array('title' => '新增融合敏捷、融合瀑布管理模型,瀑布项目阶段支持无限级拆分,后台进行全新UI改版。', 'desc' => '');
|
||||
$lang->misc->feature->all['18.2'][] = array('title' => '新增融合敏捷、融合瀑布管理模型,瀑布项目阶段支持无限级拆分,后台进行全新UI改版。修复Bug。', 'desc' => '');
|
||||
$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' => '');
|
||||
|
||||
@@ -77,7 +77,7 @@ $(function()
|
||||
|
||||
function showEditCheckbox(show)
|
||||
{
|
||||
$('.icon-project,.icon-waterfall,.icon-scrum,.icon-kanban').each(function()
|
||||
$('.icon-project,.icon-waterfall,.icon-scrum,.icon-kanban,.icon-agileplus,.icon-waterfallplus').each(function()
|
||||
{
|
||||
$this = $(this);
|
||||
$tr = $(this).closest('tr');
|
||||
|
||||
@@ -123,7 +123,7 @@ class programplanModel extends model
|
||||
*/
|
||||
public function getPairs($executionID, $productID = 0, $type = 'all')
|
||||
{
|
||||
$plans = $this->getStage($executionID, $productID, 'all', $orderBy);
|
||||
$plans = $this->getStage($executionID, $productID, $type);
|
||||
|
||||
$pairs = array(0 => '');
|
||||
|
||||
@@ -1027,17 +1027,26 @@ class programplanModel extends model
|
||||
$stage = $this->dao->select('id,type,parent,path,grade')->from(TABLE_PROJECT)->where('id')->eq($planID)->fetch();
|
||||
$parent = $this->dao->select('id,type,parent,path,grade')->from(TABLE_PROJECT)->where('id')->eq($stage->parent)->fetch();
|
||||
|
||||
$this->loadModel('execution');
|
||||
if($parent->type == 'project')
|
||||
{
|
||||
$path['path'] = ",{$parent->id},{$stage->id},";
|
||||
$path['grade'] = 1;
|
||||
}
|
||||
elseif($parent->type == 'stage')
|
||||
elseif(isset($this->lang->execution->typeList[$parent->type]))
|
||||
{
|
||||
$path['path'] = $parent->path . "{$stage->id},";
|
||||
$path['grade'] = $parent->grade + 1;
|
||||
|
||||
$children = $this->execution->getChildExecutions($planID);
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_PROJECT)->set('path')->eq($path['path'])->set('grade')->eq($path['grade'])->where('id')->eq($stage->id)->exec();
|
||||
|
||||
if(count($children) > 0)
|
||||
{
|
||||
foreach($children as $id => $child) $this->setTreePath($id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1478,8 +1487,9 @@ class programplanModel extends model
|
||||
*/
|
||||
public function computeProgress($stageID, $action = '', $isParent = false)
|
||||
{
|
||||
$stage = $this->loadModel('execution')->getByID($stageID);
|
||||
if(empty($stage) or empty($stage->path) or $stage->type != 'stage') return false;
|
||||
$stage = $this->loadModel('execution')->getByID($stageID);
|
||||
$project = $this->loadModel('project')->getByID($stage->project);
|
||||
if(empty($stage) or empty($stage->path) or ($project->model != 'waterfall' and $project->model != 'waterfallplus')) return false;
|
||||
|
||||
$this->loadModel('execution');
|
||||
$this->loadModel('action');
|
||||
@@ -1489,7 +1499,7 @@ class programplanModel extends model
|
||||
foreach($parentIdList as $id)
|
||||
{
|
||||
$parent = $this->execution->getByID($id);
|
||||
if($parent->type != 'stage' or (!$isParent and $id == $stageID)) continue;
|
||||
if(empty($this->lang->execution->typeList[$parent->type]) or (!$isParent and $id == $stageID)) continue;
|
||||
|
||||
$statusCount = array();
|
||||
$children = $this->execution->getChildExecutions($parent->id);
|
||||
|
||||
@@ -217,12 +217,9 @@ function showEditCheckbox(show)
|
||||
|
||||
$tr.find('td:first').prepend("<div class='checkbox-primary'><input type='checkbox' name='executionIDList[]' value='" + executionID + "' id='executionIDList" + executionID + "'/><label for='executionIDList" + executionID + "'></lable></div>");
|
||||
$tr.find('td:first').find('.checkbox-primary').css('margin-left', marginLeft).css('width', '14');
|
||||
$tr.find('td:first').find('span.table-nest-icon').css('margin-left', '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
var marginLeft = $tr.find('td:first').find('.checkbox-primary').css('margin-left');
|
||||
$tr.find('td:first').find('span.table-nest-icon').css('margin-left', marginLeft);
|
||||
$tr.find('td:first').find('[name^="executionIDList"]').parent().remove();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -438,6 +438,8 @@ class projectModel extends model
|
||||
foreach($projectList as $projectID => $stageList)
|
||||
{
|
||||
$progress = 0;
|
||||
$projectConsumed = 0;
|
||||
$projectLeft = 0;
|
||||
foreach($stageList as $stageID => $stage)
|
||||
{
|
||||
if($stage->project != $projectID) continue;
|
||||
@@ -445,10 +447,13 @@ class projectModel extends model
|
||||
$stageTotalConsumed = isset($totalHour[$projectID][$stageID]) ? $totalHour[$projectID][$stageID]->totalConsumed : 0;
|
||||
$stageTotalLeft = isset($totalHour[$projectID][$stageID]) ? round($totalHour[$projectID][$stageID]->totalLeft, 1) : 0;
|
||||
|
||||
$stageProgress = ($stageTotalConsumed + $stageTotalLeft) ? floor($stageTotalConsumed / ($stageTotalConsumed + $stageTotalLeft) * 1000) / 1000 * 100 : 0;
|
||||
$projectConsumed += $stageTotalConsumed;
|
||||
$projectLeft += $stageTotalLeft;
|
||||
|
||||
$progress += $stageProgress * ($stage->percent / 100);
|
||||
}
|
||||
|
||||
$progress += ($projectConsumed + $projectLeft) == 0 ? 0 : floor($projectConsumed / ($projectConsumed + $projectLeft) * 1000) / 1000 * 100;
|
||||
|
||||
$progressList[$projectID] = $progress;
|
||||
}
|
||||
|
||||
@@ -1520,7 +1525,7 @@ class projectModel extends model
|
||||
->setDefault('team', $this->post->name)
|
||||
->setDefault('lastEditedBy', $this->app->user->account)
|
||||
->setDefault('lastEditedDate', helper::now())
|
||||
->setDefault('parent', 0)
|
||||
->setDefault('parent', $oldProject->parent)
|
||||
->setIF($this->post->delta == 999, 'end', LONG_TIME)
|
||||
->setIF($this->post->delta == 999, 'days', 0)
|
||||
->setIF($this->post->begin == '0000-00-00', 'begin', '')
|
||||
@@ -2709,6 +2714,13 @@ class projectModel extends model
|
||||
->andWhere('deleted')->eq(0)
|
||||
->fetchGroup('execution', 'id');
|
||||
|
||||
$projects = $this->dao->select('t1.id,t2.model')
|
||||
->from(TABLE_PROJECT)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
|
||||
->where('t1.deleted')->eq('0')
|
||||
->andWhere('t1.id')->in(array_keys($executions))
|
||||
->fetchPairs();
|
||||
|
||||
/* Compute totalEstimate, totalConsumed, totalLeft. */
|
||||
foreach($tasks as $executionID => $executionTasks)
|
||||
{
|
||||
@@ -2721,7 +2733,7 @@ class projectModel extends model
|
||||
}
|
||||
$hours[$executionID] = $hour;
|
||||
|
||||
if(isset($executions[$executionID]) and $executions[$executionID]->type == 'stage' and $executions[$executionID]->grade > 1)
|
||||
if(isset($executions[$executionID]) and $executions[$executionID]->grade > 1 and isset($projects[$executionID]) and ($projects[$executionID] == 'waterfall' or $projects[$executionID] == 'waterfallplus'))
|
||||
{
|
||||
$stageParents = $this->dao->select('id')->from(TABLE_EXECUTION)->where('id')->in(trim($executions[$executionID]->path, ','))->andWhere('type')->eq('stage')->andWhere('id')->ne($executions[$executionID]->id)->orderBy('grade')->fetchPairs();
|
||||
foreach($stageParents as $stageParent)
|
||||
|
||||
@@ -119,7 +119,9 @@
|
||||
<div class="detail-content article-content">
|
||||
<div><span class="text-limit hidden" data-limit-size="40"><?php echo $project->desc;?></span><a class="text-primary text-limit-toggle small" data-text-expand="<?php echo $lang->expand;?>" data-text-collapse="<?php echo $lang->collapse;?>"></a></div>
|
||||
<p>
|
||||
<?php if($config->vision == 'rnd'):?>
|
||||
<span class="label label-primary label-outline"><?php echo zget($lang->project->projectTypeList, $project->hasProduct);?></span>
|
||||
<?php endif; ?>
|
||||
<?php if($project->deleted):?>
|
||||
<span class='label label-danger label-outline'><?php echo $lang->project->deleted;?></span>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -511,9 +511,11 @@ class story extends control
|
||||
$execution = $this->dao->findById((int)$executionID)->from(TABLE_EXECUTION)->fetch();
|
||||
if($execution->type == 'project')
|
||||
{
|
||||
$model = $execution->model == 'waterfallplus' ? 'waterfall' : $execution->model;
|
||||
$model = $execution->model == 'agileplus' ? 'scrum' : $model;
|
||||
$this->project->setMenu($executionID);
|
||||
$this->lang->navGroup->story = 'project';
|
||||
$this->lang->product->menu = $this->lang->{$execution->model}->menu;
|
||||
$this->lang->product->menu = $this->lang->{$model}->menu;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -926,9 +926,6 @@ class storyModel extends model
|
||||
->setDefault('assignedDate', $oldStory->assignedDate)
|
||||
->setDefault('lastEditedBy', $this->app->user->account)
|
||||
->setDefault('reviewedBy', $oldStory->reviewedBy)
|
||||
->setDefault('title', $oldStory->title)
|
||||
->setDefault('spec', $oldStory->spec)
|
||||
->setDefault('verify', $oldStory->verify)
|
||||
->setDefault('mailto', '')
|
||||
->setDefault('deleteFiles', array())
|
||||
->add('id', $storyID)
|
||||
@@ -945,6 +942,9 @@ class storyModel extends model
|
||||
->setIF(!in_array($this->post->source, $this->config->story->feedbackSource), 'feedbackBy', '')
|
||||
->setIF(!in_array($this->post->source, $this->config->story->feedbackSource), 'notifyEmail', '')
|
||||
->setIF(!empty($_POST['plan'][0]) and $oldStory->stage == 'wait', 'stage', 'planned')
|
||||
->setIF(!isset($_POST['title']), 'title', $oldStory->title)
|
||||
->setIF(!isset($_POST['spec']), 'spec', $oldStory->spec)
|
||||
->setIF(!isset($_POST['verify']), 'verify', $oldStory->verify)
|
||||
->stripTags($this->config->story->editor->edit['id'], $this->config->allowedTags)
|
||||
->join('mailto', ',')
|
||||
->join('linkStories', ',')
|
||||
|
||||
@@ -2088,7 +2088,7 @@ class task extends control
|
||||
{
|
||||
$execution = $this->execution->getById($executionID);
|
||||
$allExportFields = $this->config->task->exportFields;
|
||||
if($execution->lifetime == 'ops') $allExportFields = str_replace(' story,', '', $allExportFields);
|
||||
if($execution->lifetime == 'ops' or in_array($execution->attribute, array('request', 'review'))) $allExportFields = str_replace(' story,', '', $allExportFields);
|
||||
|
||||
if($_POST)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,40 @@
|
||||
$(function()
|
||||
{
|
||||
if(attribute == 'request' || attribute == 'review')
|
||||
{
|
||||
$('#story').closest('tr').hide();
|
||||
$("input[name='after'][value='toStoryList']").parent().hide();
|
||||
$("input[name='after'][value='continueAdding']").parent().hide();
|
||||
$("input[name='after'][value='toTaskList']").prop('checked', true);
|
||||
$("input[name='after'][value='toTaskList']").parent().css('margin-left', '0px');
|
||||
}
|
||||
|
||||
execAttribute = attribute;
|
||||
$('#execution').change(function()
|
||||
{
|
||||
link = createLink('execution', 'ajaxGetAttribute', "executionID=" + $('#execution').val());
|
||||
$.get(link, function(attribute)
|
||||
{
|
||||
execAttribute = attribute;
|
||||
if(attribute == 'request' || attribute == 'review')
|
||||
{
|
||||
$('#story').closest('tr').hide();
|
||||
$("input[name='after'][value='toStoryList']").parent().hide();
|
||||
$("input[name='after'][value='continueAdding']").parent().hide();
|
||||
$("input[name='after'][value='toTaskList']").prop('checked', true);
|
||||
$("input[name='after'][value='toTaskList']").parent().css('margin-left', '0px');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#story').closest('tr').show();
|
||||
$("input[name='after'][value='toStoryList']").parent().show();
|
||||
$("input[name='after'][value='continueAdding']").parent().show();
|
||||
$("input[name='after'][value='continueAdding']").prop('checked', true);
|
||||
$("input[name='after'][value='toTaskList']").parent().css('margin-left', '10px');
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
$('#customField').click(function()
|
||||
{
|
||||
hiddenRequireFields();
|
||||
|
||||
@@ -75,7 +75,7 @@ $colspan = count($visibleFields) + 3;
|
||||
<th class='c-module'><?php echo $lang->kanbancard->region;?></th>
|
||||
<th class='c-module'><?php echo $lang->kanbancard->lane;?></th>
|
||||
<?php endif;?>
|
||||
<th class='c-type required'><?php echo $lang->typeAB;?></span></th>
|
||||
<th class='c-type required'><?php echo $lang->task->type;?></span></th>
|
||||
<th class='c-assigned<?php echo zget($visibleFields, 'assignedTo', ' hidden') . zget($requiredFields, 'assignedTo', '', ' required');?> assignedToBox'><?php echo $lang->task->assignedTo;?></th>
|
||||
<th class='c-estimate<?php echo zget($visibleFields, 'estimate', ' hidden') . zget($requiredFields, 'estimate', '', ' required');?> estimateBox'><?php echo $lang->task->estimateAB;?></th>
|
||||
<th class='c-date<?php echo zget($visibleFields, 'estStarted', ' hidden') . zget($requiredFields, 'estStarted', '', ' required');?> estStartedBox'><?php echo $lang->task->estStarted;?></th>
|
||||
|
||||
@@ -59,7 +59,7 @@ js::set('requiredFields', $config->task->edit->requiredFields);
|
||||
<th class='required <?php if(count($visibleFields) > 10) echo 'c-name';?>'><?php echo $lang->task->name?></th>
|
||||
<th class='c-module<?php echo zget($visibleFields, 'module', ' hidden') . zget($requiredFields, 'module', '', ' required');?>'><?php echo $lang->task->module?></th>
|
||||
<th class='c-assigned<?php echo zget($visibleFields, 'assignedTo', ' hidden') . zget($requiredFields, 'assignedTo', '', ' required');?>'><?php echo $lang->task->assignedTo;?></th>
|
||||
<th class='c-type required'><?php echo $lang->typeAB; ?></th>
|
||||
<th class='c-type required'><?php echo $lang->task->type; ?></th>
|
||||
<th class='c-status<?php echo zget($visibleFields, 'status', ' hidden') . zget($requiredFields, 'status', '', ' required');?>'><?php echo $lang->task->status;?></th>
|
||||
<th class='c-date<?php echo zget($visibleFields, 'estStarted', ' hidden') . zget($requiredFields, 'estStarted', '', ' required');?>'><?php echo $lang->task->estStarted?></th>
|
||||
<th class='c-date<?php echo zget($visibleFields, 'deadline', ' hidden') . zget($requiredFields, 'deadline', '', ' required');?>'><?php echo $lang->task->deadline?></th>
|
||||
|
||||
@@ -110,7 +110,7 @@ foreach(explode(',', $config->task->create->requiredFields) as $field)
|
||||
<td><?php echo html::hidden('status', 'wait');?></td>
|
||||
</tr>
|
||||
<?php $this->printExtendFields('', 'table', 'columns=3');?>
|
||||
<?php $hiddenStory = (strpos(",$showFields,", ',story,') !== false and $execution->lifetime != 'ops') ? '' : 'hidden'?>
|
||||
<?php $hiddenStory = (strpos(",$showFields,", ',story,') !== false and $execution->lifetime != 'ops' and !in_array($execution->attribute, array('request', 'review'))) ? '' : 'hidden'?>
|
||||
<tr class="<?php echo $hiddenStory?> storyBox">
|
||||
<th><?php echo $lang->task->story;?></th>
|
||||
<td colspan='3'>
|
||||
@@ -129,7 +129,7 @@ foreach(explode(',', $config->task->create->requiredFields) as $field)
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php if($execution->lifetime != 'ops'):?>
|
||||
<?php if($execution->lifetime != 'ops' and !in_array($execution->attribute, array('request', 'review'))):?>
|
||||
<tr id='testStoryBox' class='hidden'>
|
||||
<th><?php echo $lang->task->selectTestStory;?></th>
|
||||
<td colspan='3'>
|
||||
|
||||
@@ -67,6 +67,11 @@ class transfer extends control
|
||||
$this->config->transfer->sysDataList = $this->transfer->initSysDataFields();
|
||||
|
||||
$fields = $this->config->$model->templateFields;
|
||||
if($model == 'task')
|
||||
{
|
||||
$execution = $this->loadModel('execution')->getByID($executionID);
|
||||
if(isset($execution) and $execution->type == 'ops' or in_array($execution->attribute, array('request', 'review'))) $fields = str_replace('story,', '', $fields);
|
||||
}
|
||||
|
||||
/* Init config fieldList. */
|
||||
$fieldList = $this->transfer->initFieldList($model, $fields);
|
||||
|
||||
@@ -360,7 +360,13 @@ $(function()
|
||||
else
|
||||
{
|
||||
var menuModule = task.nav.menuModule || task.nav['module'];
|
||||
var $navbar = $$('#navbar');
|
||||
var $navbar = $$('#navbar');
|
||||
var adminMenu = false;
|
||||
if(!$navbar.find('li').length)
|
||||
{
|
||||
adminMenu = true;
|
||||
$navbar = $$('.settings-list');
|
||||
}
|
||||
var $navbarItem = $navbar.find('[data-id="' + menuModule + '"]');
|
||||
var targetPageTip = lang.targetPageTip.replace('%s', task.nav.targetPageName || lang.target);
|
||||
if($navbarItem.length && !$navbarItem.hasClass('active'))
|
||||
@@ -408,6 +414,7 @@ $(function()
|
||||
else
|
||||
{
|
||||
var $modulemenu = $$('#subNavbar');
|
||||
if(task.nav.app == 'admin') $modulemenu = $$('#navbar');
|
||||
var $modulemenuItem = $modulemenu.find('[data-id="' + task.nav.menu + '"]');
|
||||
if($modulemenuItem.length && !$modulemenuItem.hasClass('active'))
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ $lang->tutorial->tasks = array();
|
||||
|
||||
$lang->tutorial->tasks['createAccount'] = array('title' => '创建帐号');
|
||||
$lang->tutorial->tasks['createAccount']['nav'] = array('app' => 'admin', 'module' => 'user', 'method' => 'create', 'menuModule' => 'company', 'menu' => 'browseUser', 'form' => '#createForm', 'requiredFields' => 'account,realname,verifyPassword,password1,password2', 'submit' => '#submit', 'target' => '.create-user-btn', 'targetPageName' => '添加用户');
|
||||
$lang->tutorial->tasks['createAccount']['desc'] = "<p>在系统创建一个新的用户帐号:</p><ul><li data-target='nav'>打开 <span class='task-nav'>后台 <i class='icon icon-angle-right'></i> 人员 <i class='icon icon-angle-right'></i> 用户 <i class='icon icon-angle-right'></i> 添加用户</span> 页面;</li><li data-target='form'>在添加用户表单中填写新用户信息;</li><li data-target='submit'>保存用户信息。</li></ul>";
|
||||
$lang->tutorial->tasks['createAccount']['desc'] = "<p>在系统创建一个新的用户帐号:</p><ul><li data-target='nav'>打开 <span class='task-nav'>后台 <i class='icon icon-angle-right'></i> 人员管理 <i class='icon icon-angle-right'></i> 用户 <i class='icon icon-angle-right'></i> 添加用户</span> 页面;</li><li data-target='form'>在添加用户表单中填写新用户信息;</li><li data-target='submit'>保存用户信息。</li></ul>";
|
||||
|
||||
$lang->tutorial->tasks['createProgram'] = array('title' => '创建项目集');
|
||||
$lang->tutorial->tasks['createProgram']['nav'] = array('app' => 'program', 'module' => 'program', 'method' => 'create', 'menuModule' => 'program', 'menu' => '#heading>.header-btn:first,#navbar>.nav>li[data-id="browse"],.create-program-btn', 'form' => '#dataform', 'submit' => '#submit', 'target' => '.create-program-btn', 'targetPageName' => '添加项目集');
|
||||
|
||||
@@ -94,8 +94,8 @@ $lang->upgrade->productCount = "%s个{$lang->productCommon}";
|
||||
$lang->upgrade->projectCount = "%s个{$lang->projectCommon}";
|
||||
$lang->upgrade->mergeByProject = "当前提供如下2种数据迁移方式,如果历史的{$lang->projectCommon}都是长周期的,那么我们建议把历史的{$lang->projectCommon}作为项目升级。</br>如果历史的{$lang->projectCommon}都是短周期的,那么我们建议把历史的{$lang->projectCommon}作为{$lang->executionCommon}升级。";
|
||||
$lang->upgrade->mergeRepoTips = "将选中的版本库归并到所选产品下。";
|
||||
$lang->upgrade->needBuild4Add = '本次升级需要创建索引。请到 [后台->系统->重建索引] 页面,重新创建索引。';
|
||||
$lang->upgrade->needChangeEngine = '本次升级需要更换表引擎, [后台->系统->表引擎] 页面更换引擎。';
|
||||
$lang->upgrade->needBuild4Add = '本次升级需要创建索引。请到 [后台->系统设置->重建索引] 页面,重新创建索引。';
|
||||
$lang->upgrade->needChangeEngine = '本次升级需要更换表引擎, [后台->系统设置->表引擎] 页面更换引擎。';
|
||||
$lang->upgrade->errorEngineInnodb = '您当前的数据库不支持使用InnoDB数据表引擎,请修改为MyISAM后重试。';
|
||||
$lang->upgrade->duplicateProject = "同一个项目集内项目名称不能重复,请调整重名的项目名称";
|
||||
$lang->upgrade->upgradeTips = "历史删除数据不参与升级,升级后将不支持还原,请知悉";
|
||||
@@ -138,4 +138,4 @@ $lang->upgrade->recoveryActions->cancel = '取消';
|
||||
$lang->upgrade->recoveryActions->review = '评审';
|
||||
|
||||
$lang->upgrade->remark = '备注';
|
||||
$lang->upgrade->remarkDesc = '后续您还可以在禅道的后台-系统-模式中进行切换。';
|
||||
$lang->upgrade->remarkDesc = '后续您还可以在禅道的后台-系统设置-模式中进行切换。';
|
||||
|
||||
@@ -21,3 +21,4 @@
|
||||
.icon-refresh {font-size: 15px;}
|
||||
.load-indicator:after {top: 33%;}
|
||||
.btn.disabled i {color: #fff;}
|
||||
#statusContainer{min-height: 120px;}
|
||||
|
||||
@@ -35,6 +35,7 @@ function ajaxGetServiceStatus()
|
||||
|
||||
setTimeout(function() {
|
||||
$('#serviceContent').removeClass('loading');
|
||||
$(".service-status, .status-notice").show()
|
||||
}, 500);
|
||||
});
|
||||
return
|
||||
|
||||
@@ -16,6 +16,7 @@ $lang->zahost->browseNode = 'ZAnode Browse';
|
||||
$lang->zahost->deleted = "Deleted";
|
||||
$lang->zahost->copy = 'Click to copy';
|
||||
$lang->zahost->copied = 'Copy successful';
|
||||
$lang->zahost->baseInfo = 'Basic information';
|
||||
|
||||
$lang->zahost->name = 'Name';
|
||||
$lang->zahost->IP = 'Extranet Address';
|
||||
@@ -92,7 +93,7 @@ $lang->zahost->image->statusList['created'] = 'Inprogress';
|
||||
$lang->zahost->image->statusList['canceled'] = 'Not Downloaded';
|
||||
$lang->zahost->image->statusList['inprogress'] = 'Inprogress';
|
||||
$lang->zahost->image->statusList['pending'] = 'Waiting for download';
|
||||
$lang->zahost->image->statusList['completed'] = 'Completed';
|
||||
$lang->zahost->image->statusList['completed'] = 'Usable';
|
||||
$lang->zahost->image->statusList['failed'] = 'Failed';
|
||||
|
||||
$lang->zahost->image->imageEmpty = 'No Image';
|
||||
|
||||
@@ -16,6 +16,7 @@ $lang->zahost->browseNode = 'ZAnode Browse';
|
||||
$lang->zahost->deleted = "Deleted";
|
||||
$lang->zahost->copy = 'Click to copy';
|
||||
$lang->zahost->copied = 'Copy successful';
|
||||
$lang->zahost->baseInfo = 'Basic information';
|
||||
|
||||
$lang->zahost->name = 'Name';
|
||||
$lang->zahost->IP = 'Extranet Address';
|
||||
@@ -92,7 +93,7 @@ $lang->zahost->image->statusList['created'] = 'Inprogress';
|
||||
$lang->zahost->image->statusList['canceled'] = 'Not Downloaded';
|
||||
$lang->zahost->image->statusList['inprogress'] = 'Inprogress';
|
||||
$lang->zahost->image->statusList['pending'] = 'Waiting for download';
|
||||
$lang->zahost->image->statusList['completed'] = 'Completed';
|
||||
$lang->zahost->image->statusList['completed'] = 'Usable';
|
||||
$lang->zahost->image->statusList['failed'] = 'Failed';
|
||||
|
||||
$lang->zahost->image->imageEmpty = 'No Image';
|
||||
|
||||
@@ -16,6 +16,7 @@ $lang->zahost->browseNode = 'ZAnode Browse';
|
||||
$lang->zahost->deleted = "Deleted";
|
||||
$lang->zahost->copy = 'Click to copy';
|
||||
$lang->zahost->copied = 'Copy successful';
|
||||
$lang->zahost->baseInfo = 'Basic information';
|
||||
|
||||
$lang->zahost->name = 'Name';
|
||||
$lang->zahost->IP = 'Extranet Address';
|
||||
@@ -92,7 +93,7 @@ $lang->zahost->image->statusList['created'] = 'Inprogress';
|
||||
$lang->zahost->image->statusList['canceled'] = 'Not Downloaded';
|
||||
$lang->zahost->image->statusList['inprogress'] = 'Inprogress';
|
||||
$lang->zahost->image->statusList['pending'] = 'Waiting for download';
|
||||
$lang->zahost->image->statusList['completed'] = 'Completed';
|
||||
$lang->zahost->image->statusList['completed'] = 'Usable';
|
||||
$lang->zahost->image->statusList['failed'] = 'Failed';
|
||||
|
||||
$lang->zahost->image->imageEmpty = 'No Image';
|
||||
|
||||
@@ -91,7 +91,7 @@ $lang->zahost->image->statusList['created'] = 'Inprogress';
|
||||
$lang->zahost->image->statusList['canceled'] = 'Not Downloaded';
|
||||
$lang->zahost->image->statusList['inprogress'] = 'Inprogress';
|
||||
$lang->zahost->image->statusList['pending'] = 'Waiting for download';
|
||||
$lang->zahost->image->statusList['completed'] = 'Completed';
|
||||
$lang->zahost->image->statusList['completed'] = 'Usable';
|
||||
$lang->zahost->image->statusList['failed'] = 'Failed';
|
||||
|
||||
$lang->zahost->image->imageEmpty = 'No Image';
|
||||
|
||||
@@ -16,6 +16,7 @@ $lang->zahost->browseNode = '执行节点列表';
|
||||
$lang->zahost->deleted = "已删除";
|
||||
$lang->zahost->copy = '复制';
|
||||
$lang->zahost->copied = '复制成功';
|
||||
$lang->zahost->baseInfo = '基础信息';
|
||||
|
||||
$lang->zahost->name = '名称';
|
||||
$lang->zahost->IP = 'IP/域名';
|
||||
|
||||
@@ -590,6 +590,7 @@ class zahostModel extends model
|
||||
*/
|
||||
public function getServiceStatus($host)
|
||||
{
|
||||
if(in_array($host->status, array('wait', 'offline'))) return $this->lang->zahost->init->serviceStatus;
|
||||
$result = json_decode(commonModel::http("http://{$host->extranet}:{$host->zap}/api/v1/service/check", json_encode(array("services" => "all")), array(), array("Authorization:$host->tokenSN")));
|
||||
if(empty($result) || $result->code != 'success')
|
||||
{
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<div class="col-8 main-col">
|
||||
<div class="cell">
|
||||
<div class="detail zahost-detail">
|
||||
<div class="detail-title"><?php echo $lang->zahost->view;?></div>
|
||||
<div class="detail-title"><?php echo $lang->zahost->baseInfo;?></div>
|
||||
<div class="detail-content article-content">
|
||||
<div class="main-row zanode-mt-8">
|
||||
<div class="col-4">
|
||||
@@ -95,6 +95,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail zahost-detail">
|
||||
<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>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<div class="detail zahost-detail">
|
||||
@@ -105,10 +109,7 @@
|
||||
<div class="detail-content article-content load-indicator" id='serviceContent'>
|
||||
<div class="main-row">
|
||||
<div id="statusContainer">
|
||||
<div class="text-kvm"><span class="dot-symbol fail"> ●</span><span>KVM</span></div>
|
||||
<div class="text-kvm"><span class="dot-symbol fail"> ●</span><span>Nginx</span></div>
|
||||
<div class="text-kvm"><span class="dot-symbol fail"> ●</span><span>noVNC</span></div>
|
||||
<div class="text-kvm"><span class="dot-symbol fail"> ●</span><span>Websockify</span></div>
|
||||
|
||||
</div>
|
||||
<div class='result'>
|
||||
<?php $imageLink = html::a($this->createLink('zahost', 'browseImage', "hostID=$zahost->id", '', true), $lang->zahost->image->downloadImage, '', "class='iframe'");?>
|
||||
@@ -126,12 +127,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<div class="detail zahost-detail">
|
||||
<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>
|
||||
</div>
|
||||
<?php if(commonModel::hasPriv('zanode', 'browse')):?>
|
||||
<div class="cell">
|
||||
<div class="detail">
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
$config->zanode->create = new stdClass();
|
||||
$config->zanode->edit = new stdClass();
|
||||
$config->zanode->createimage = new stdClass();
|
||||
$config->zanode->create->requiredFields = 'name,host,image,cpu,memory,disk,osName';
|
||||
$config->zanode->edit->requiredFields = '';
|
||||
$config->zanode->createimage->requiredFields = 'name';
|
||||
$config->zanode->create->requiredFields = 'name,host,image,cpu,memory,disk,osName';
|
||||
$config->zanode->create->physicsRequiredFields = 'name,extranet,cpu,memory,osName';
|
||||
$config->zanode->edit->requiredFields = '';
|
||||
$config->zanode->createimage->requiredFields = 'name';
|
||||
|
||||
$config->zanode->defaultPort = '55001';
|
||||
$config->zanode->defaultAccount = 'z';
|
||||
|
||||
@@ -137,10 +137,15 @@ class zanode extends control
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->zanode->editAction;
|
||||
$this->view->zanode = $this->zanode->getNodeByID($id);
|
||||
$this->view->host = $this->zanode->getHostByID($this->view->zanode->parent);
|
||||
$this->view->image = $this->zanode->getImageByID($this->view->zanode->image);
|
||||
$zanode = $this->zanode->getNodeByID($id);
|
||||
|
||||
$this->view->title = $this->lang->zanode->editAction;
|
||||
$this->view->zanode = $zanode;
|
||||
if($zanode->type == 'node')
|
||||
{
|
||||
$this->view->host = $this->zanode->getHostByID($this->view->zanode->parent);
|
||||
$this->view->image = $this->zanode->getImageByID($this->view->zanode->image);
|
||||
}
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -243,9 +248,7 @@ class zanode extends control
|
||||
|
||||
if($error)
|
||||
{
|
||||
$response['result'] = 'fail';
|
||||
$response['message'] = $error;
|
||||
return $this->send($response);
|
||||
return print(js::alert($error) . js::reload('parent'));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -558,7 +561,7 @@ class zanode extends control
|
||||
{
|
||||
$node = $this->zanode->getNodeById($hostID);
|
||||
$serviceStatus = $this->zanode->getServiceStatus($node);
|
||||
if ($node->status != 'running' && $node->status != 'wait')
|
||||
if ($node->status != 'running')
|
||||
{
|
||||
$serviceStatus['ZenAgent'] = "unknown";
|
||||
$serviceStatus['ZTF'] = "unknown";
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
.c-status {width: 70px;}
|
||||
.c-cpu, .c-host {width: 100px;}
|
||||
.c-ip{width: 150px;}
|
||||
.c-os {width: 120px;}
|
||||
.c-os, .c-type {width: 120px;}
|
||||
.desktop, .createImage{margin-right: 4px;}
|
||||
#helpTab .icon-help {line-height: unset;}
|
||||
#bysearchTab {margin-right: 0px;}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.c-type {width: 80px;}
|
||||
@@ -17,3 +17,4 @@
|
||||
.node-not-wrap{white-space: nowrap;}
|
||||
.btn-info {background-color: unset;}
|
||||
.btn.disabled i {color: #fff;}
|
||||
#serviceContent{min-height: 120px;}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
function zahostType()
|
||||
{
|
||||
if($('#type').val() == 'physics')
|
||||
{
|
||||
$('#parent').closest('tr').hide();
|
||||
$('#image').closest('tr').hide();
|
||||
$('#extranet').closest('tr').removeClass('hidden');
|
||||
$('#osName').addClass('hidden');
|
||||
$('#osNamePhysics').removeClass('hidden');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#parent').closest('tr').show();
|
||||
$('#image').closest('tr').show();
|
||||
$('#extranet').closest('tr').addClass('hidden');
|
||||
$('#osName').removeClass('hidden');
|
||||
$('#osNamePhysics').addClass('hidden');
|
||||
}
|
||||
}
|
||||
@@ -99,6 +99,7 @@ function checkServiceStatus(){
|
||||
}
|
||||
setTimeout(function() {
|
||||
$('#serviceContent').removeClass('loading');
|
||||
$(".service-status, .status-notice").show()
|
||||
}, 500);
|
||||
});
|
||||
return
|
||||
@@ -186,7 +187,7 @@ $('#jumpManual').click(function()
|
||||
|
||||
|
||||
$(function(){
|
||||
checkServiceStatus();
|
||||
$('#checkServiceStatus').trigger("click")
|
||||
checkInterval = setInterval(() => {
|
||||
intervalTimes++;
|
||||
if(intervalTimes > 300)
|
||||
|
||||
@@ -48,6 +48,7 @@ $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 = "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";
|
||||
@@ -62,6 +63,9 @@ $lang->zanode->initializing = 'Initializing';
|
||||
$lang->zanode->showPwd = 'Show Password';
|
||||
$lang->zanode->hidePwd = 'Hide Password';
|
||||
|
||||
$lang->zanode->typeList['node'] = 'Virtual machine';
|
||||
$lang->zanode->typeList['physics'] = 'Physical machine';
|
||||
|
||||
$lang->automation = new stdClass();
|
||||
$lang->automation->scriptPath = $lang->zanode->scriptPath;
|
||||
$lang->automation->node = $lang->zanode->common;
|
||||
@@ -72,6 +76,7 @@ $lang->zanode->noVncPort = 'Failed to get vnc port';
|
||||
$lang->zanode->nameValid = "The name can only be letters, numbers, '-', '_', '.', and cannot start with a symbol";
|
||||
$lang->zanode->empty = 'No zanode is found';
|
||||
$lang->zanode->runCaseConfirm = 'The system detects the presence of an automation script. Whether to execute?';
|
||||
$lang->zanode->netError = 'Unable to connect to the physical machine, please check the network and try again.';
|
||||
|
||||
$lang->zanode->createImage = 'Create Image';
|
||||
$lang->zanode->createImaging = 'Creating';
|
||||
@@ -85,19 +90,26 @@ $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->restoreSnapshot = 'Revert From This 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 = new stdClass();
|
||||
$lang->zanode->snapshot->statusList['creating'] = 'Creating';
|
||||
$lang->zanode->snapshot->statusList['completed'] = 'Create Completed';
|
||||
$lang->zanode->snapshot->statusList['inprogress'] = 'Creating';
|
||||
$lang->zanode->snapshot->statusList['completed'] = 'Usable';
|
||||
$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->snapshot->statusList['restore_completed'] = 'Usable';
|
||||
|
||||
$lang->zanode->imageNameEmpty = 'Name can not be empty.';
|
||||
$lang->zanode->snapshot->defaultSnapName = 'DefaultSnapshot';
|
||||
$lang->zanode->snapshot->defaultSnapUser = 'System';
|
||||
|
||||
$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.';
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ $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";
|
||||
@@ -64,6 +63,9 @@ $lang->zanode->initializing = 'Initializing';
|
||||
$lang->zanode->showPwd = 'Show Password';
|
||||
$lang->zanode->hidePwd = 'Hide Password';
|
||||
|
||||
$lang->zanode->typeList['node'] = 'Virtual machine';
|
||||
$lang->zanode->typeList['physics'] = 'Physical machine';
|
||||
|
||||
$lang->automation = new stdClass();
|
||||
$lang->automation->scriptPath = $lang->zanode->scriptPath;
|
||||
$lang->automation->node = $lang->zanode->common;
|
||||
@@ -74,6 +76,7 @@ $lang->zanode->noVncPort = 'Failed to get vnc port';
|
||||
$lang->zanode->nameValid = "The name can only be letters, numbers, '-', '_', '.', and cannot start with a symbol";
|
||||
$lang->zanode->empty = 'No zanode is found';
|
||||
$lang->zanode->runCaseConfirm = 'The system detects the presence of an automation script. Whether to execute?';
|
||||
$lang->zanode->netError = 'Unable to connect to the physical machine, please check the network and try again.';
|
||||
|
||||
$lang->zanode->createImage = 'Create Image';
|
||||
$lang->zanode->createImaging = 'Creating';
|
||||
@@ -87,17 +90,22 @@ $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->restoreSnapshot = 'Revert From This 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 = new stdClass();
|
||||
$lang->zanode->snapshot->statusList['creating'] = 'Creating';
|
||||
$lang->zanode->snapshot->statusList['completed'] = 'Create Completed';
|
||||
$lang->zanode->snapshot->statusList['inprogress'] = 'Creating';
|
||||
$lang->zanode->snapshot->statusList['completed'] = 'Usable';
|
||||
$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->snapshot->statusList['restore_completed'] = 'Usable';
|
||||
|
||||
$lang->zanode->snapshot->defaultSnapName = 'DefaultSnapshot';
|
||||
$lang->zanode->snapshot->defaultSnapUser = 'System';
|
||||
|
||||
$lang->zanode->imageNameEmpty = 'Name can not be empty.';
|
||||
$lang->zanode->snapStatusError = 'Snapshot is not ready.';
|
||||
@@ -151,8 +159,8 @@ $lang->zanode->init->title = "Initialize Node";
|
||||
$lang->zanode->init->descTitle = "Follow these steps to complete the initialization on the node:";
|
||||
$lang->zanode->init->initDesc = "Execute the init script on the node: %s %s <br>- Click check service status button.";
|
||||
|
||||
$lang->zanode->tips = "The execution node is a virtual machine or container instance created by the host machine, which is a test environment for executing test tasks. After the execution node is configured with the automated test environment, the script can be automatically executed, and the results can be viewed in the execution results of Zen Dao's application cases.";
|
||||
$lang->zanode->scriptTips = 'Write the directory where the script is located on the execution node.';
|
||||
$lang->zanode->shellTips = 'Before running the automated test script on the execution node, you can execute a custom shell command.';
|
||||
$lang->zanode->tips = "The execution node is a virtual machine or container instance created by the host machine, which is a test environment for executing test tasks. After the execution node is configured with the automated test environment, the script can be automatically executed, and the results can be viewed in the execution results of Zen Dao's application cases.";
|
||||
$lang->zanode->scriptTips = 'Write the directory where the script is located on the execution node.';
|
||||
$lang->zanode->shellTips = 'Before running the automated test script on the execution node, you can execute a custom shell command.';
|
||||
$lang->zanode->automationTips = 'Before executing the test task on the execution node, you need to set up the execution node corresponding to the product, the directory of the automated test script, and the custom Shell command to execute.';
|
||||
$lang->zanode->nameUnique = $lang->zanode->name . 'already exist';
|
||||
|
||||
@@ -48,6 +48,7 @@ $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 = "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";
|
||||
@@ -62,6 +63,9 @@ $lang->zanode->initializing = 'Initializing';
|
||||
$lang->zanode->showPwd = 'Show Password';
|
||||
$lang->zanode->hidePwd = 'Hide Password';
|
||||
|
||||
$lang->zanode->typeList['node'] = 'Virtual machine';
|
||||
$lang->zanode->typeList['physics'] = 'Physical machine';
|
||||
|
||||
$lang->automation = new stdClass();
|
||||
$lang->automation->scriptPath = $lang->zanode->scriptPath;
|
||||
$lang->automation->node = $lang->zanode->common;
|
||||
@@ -72,6 +76,7 @@ $lang->zanode->noVncPort = 'Failed to get vnc port';
|
||||
$lang->zanode->nameValid = "The name can only be letters, numbers, '-', '_', '.', and cannot start with a symbol";
|
||||
$lang->zanode->empty = 'No zanode is found';
|
||||
$lang->zanode->runCaseConfirm = 'The system detects the presence of an automation script. Whether to execute?';
|
||||
$lang->zanode->netError = 'Unable to connect to the physical machine, please check the network and try again.';
|
||||
|
||||
$lang->zanode->createImage = 'Create Image';
|
||||
$lang->zanode->createImaging = 'Creating';
|
||||
@@ -85,19 +90,26 @@ $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->restoreSnapshot = 'Revert From This 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 = new stdClass();
|
||||
$lang->zanode->snapshot->statusList['creating'] = 'Creating';
|
||||
$lang->zanode->snapshot->statusList['completed'] = 'Create Completed';
|
||||
$lang->zanode->snapshot->statusList['inprogress'] = 'Creating';
|
||||
$lang->zanode->snapshot->statusList['completed'] = 'Usable';
|
||||
$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->snapshot->statusList['restore_completed'] = 'Usable';
|
||||
|
||||
$lang->zanode->imageNameEmpty = 'Name can not be empty.';
|
||||
$lang->zanode->snapshot->defaultSnapName = 'DefaultSnapshot';
|
||||
$lang->zanode->snapshot->defaultSnapUser = 'System';
|
||||
|
||||
$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.';
|
||||
|
||||
|
||||
@@ -63,6 +63,9 @@ $lang->zanode->initializing = '初始化中';
|
||||
$lang->zanode->showPwd = '显示密码';
|
||||
$lang->zanode->hidePwd = '隐藏密码';
|
||||
|
||||
$lang->zanode->typeList['node'] = '虚拟机';
|
||||
$lang->zanode->typeList['physics'] = '物理机';
|
||||
|
||||
$lang->automation = new stdClass();
|
||||
$lang->automation->scriptPath = $lang->zanode->scriptPath;
|
||||
$lang->automation->node = $lang->zanode->common;
|
||||
@@ -73,6 +76,7 @@ $lang->zanode->noVncPort = '无法获取执行节点端口';
|
||||
$lang->zanode->nameValid = "名称只能是字母、数字,'-','_','.',且不能以符号开头";
|
||||
$lang->zanode->empty = '暂时没有执行节点';
|
||||
$lang->zanode->runCaseConfirm = '系统检测到选择的用例存在自动化测试脚本,是否自动执行用例?';
|
||||
$lang->zanode->netError = '无法连接到物理机,请检查网络后重试。';
|
||||
|
||||
$lang->zanode->createImage = '导出镜像';
|
||||
$lang->zanode->createImaging = '正在导出镜像';
|
||||
@@ -86,20 +90,23 @@ $lang->zanode->snapshotName = '快照名称';
|
||||
$lang->zanode->browseSnapshot = '快照列表';
|
||||
$lang->zanode->createSnapshot = '创建快照';
|
||||
$lang->zanode->editSnapshot = '编辑快照';
|
||||
$lang->zanode->restoreSnapshot = '还原快照';
|
||||
$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['inprogress'] = '创建中';
|
||||
$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->snapshot->statusList['restore_completed'] = '可使用';
|
||||
|
||||
$lang->zanode->snapshot->defaultSnapName = '初始快照';
|
||||
$lang->zanode->snapshot->defaultSnapUser = '系统';
|
||||
|
||||
$lang->zanode->imageNameEmpty = '名称不能为空';
|
||||
$lang->zanode->imageNameEmpty = '名称不能为空';
|
||||
$lang->zanode->snapStatusError = '快照不可用';
|
||||
$lang->zanode->snapRestoring = '快照正在还原中';
|
||||
@@ -130,7 +137,7 @@ $lang->zanode->statusList['restoring'] = '还原中';
|
||||
$lang->zanode->initNotice = "保存成功,请初始化执行节点或返回列表。";
|
||||
$lang->zanode->initButton = "去初始化";
|
||||
|
||||
$lang->zanode->init = new stdclass;
|
||||
$lang->zanode->init = new stdClass();
|
||||
$lang->zanode->init->statusTitle = "服务状态";
|
||||
$lang->zanode->init->checkStatus = "检测服务状态";
|
||||
$lang->zanode->init->not_install = "未安装";
|
||||
@@ -152,8 +159,8 @@ $lang->zanode->init->title = "初始化执行节点";
|
||||
$lang->zanode->init->descTitle = "请根据引导完成执行节点上的初始化: ";
|
||||
$lang->zanode->init->initDesc = "- 在执行节点上执行命令:%s %s <br>- 点击检测服务状态。";$lang->zanode->init->statusTitle = "服务状态";
|
||||
|
||||
$lang->zanode->tips = '执行节点是由宿主机创建的虚拟机或容器实例,是执行测试任务的测试环境,在执行节点配置自动化测试环境后可以自动执行脚本,结果可以在禅道对应用例执行结果中查看。';
|
||||
$lang->zanode->scriptTips = '填写执行节点上自动化测试脚本所在的目录。';
|
||||
$lang->zanode->shellTips = '在执行节点上运行自动化测试脚本前,可以执行自定义的shell命令。';
|
||||
$lang->zanode->tips = '执行节点是由宿主机创建的虚拟机或容器实例,是执行测试任务的测试环境,在执行节点配置自动化测试环境后可以自动执行脚本,结果可以在禅道对应用例执行结果中查看。';
|
||||
$lang->zanode->scriptTips = '填写执行节点上自动化测试脚本所在的目录。';
|
||||
$lang->zanode->shellTips = '在执行节点上运行自动化测试脚本前,可以执行自定义的shell命令。';
|
||||
$lang->zanode->automationTips = '在执行节点上执行测试任务前,需要设置产品对应的执行节点,自动化测试脚本的目录以及需要执行的自定义Shell命令。';
|
||||
$lang->zanode->nameUnique = $lang->zanode->name . '已存在';
|
||||
|
||||
+101
-39
@@ -53,12 +53,15 @@ class zanodemodel extends model
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$data = fixer::input('post')->get();
|
||||
$data = fixer::input('post')
|
||||
->setIF($this->post->type == 'physics', 'parent', 0)
|
||||
->setIF($this->post->type == 'physics', 'osName', $this->post->osNamePhysics)
|
||||
->remove('osNamePhysics')
|
||||
->get();
|
||||
|
||||
/* Batch check fields. */
|
||||
$data->type = 'node';
|
||||
$this->dao->update(TABLE_ZAHOST)->data($data)
|
||||
->batchCheck($this->config->zanode->create->requiredFields, 'notempty');
|
||||
->batchCheck($data->type == 'node' ? $this->config->zanode->create->requiredFields : $this->config->zanode->create->physicsRequiredFields, 'notempty');
|
||||
|
||||
if(dao::isError()) return false;
|
||||
|
||||
@@ -69,47 +72,60 @@ class zanodemodel extends model
|
||||
}
|
||||
|
||||
/* If name already exists return error. */
|
||||
$node = $this->dao->select('*')->from(TABLE_ZAHOST)->where('name')->eq($data->name)->andWhere('type')->eq('node')->fetch();
|
||||
$node = $this->dao->select('*')->from(TABLE_ZAHOST)->where('name')->eq($data->name)->andWhere('type')->in('node,physics')->fetch();
|
||||
if($node) return dao::$errors[] = $this->lang->zanode->nameUnique;
|
||||
|
||||
/* Get image. */
|
||||
$image = $this->getImageByID($data->image);
|
||||
|
||||
/* Get host info. */
|
||||
$host = $this->getHostByID($data->parent);
|
||||
|
||||
/* Prepare create params. */
|
||||
$agnetUrl = 'http://' . $host->extranet . ':' . $host->zap;
|
||||
$param = array(
|
||||
'os' => $image->osName,
|
||||
'path' => $image->path,
|
||||
'name' => $data->name,
|
||||
'cpu' => (int)$data->cpuCores,
|
||||
'disk' => (int)$data->diskSize,
|
||||
'memory' => (int)$data->memory,
|
||||
);
|
||||
|
||||
$result = json_decode(commonModel::http($agnetUrl . static::KVM_CREATE_PATH, json_encode($param), null, array("Authorization:$host->tokenSN")));
|
||||
|
||||
if(empty($result))
|
||||
if($data->type == 'physics')
|
||||
{
|
||||
dao::$errors[] = $this->lang->zanode->notFoundAgent;
|
||||
return false;
|
||||
$ping = $this->loadModel('zahost')->checkAddress($data->extranet);
|
||||
if(!$ping)
|
||||
{
|
||||
dao::$errors[] = $this->lang->zanode->netError;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if($result->code != 'success')
|
||||
else
|
||||
{
|
||||
dao::$errors[] = $this->lang->zanode->createVmFail;
|
||||
return false;
|
||||
/* Get image. */
|
||||
$image = $this->getImageByID($data->image);
|
||||
|
||||
/* Get host info. */
|
||||
$host = $this->getHostByID($data->parent);
|
||||
|
||||
/* Prepare create params. */
|
||||
$agnetUrl = 'http://' . $host->extranet . ':' . $host->zap;
|
||||
$param = array(
|
||||
'os' => $image->osName,
|
||||
'path' => $image->path,
|
||||
'name' => $data->name,
|
||||
'cpu' => (int)$data->cpuCores,
|
||||
'disk' => (int)$data->diskSize,
|
||||
'memory' => (int)$data->memory,
|
||||
);
|
||||
|
||||
$result = json_decode(commonModel::http($agnetUrl . static::KVM_CREATE_PATH, json_encode($param), null, array("Authorization:$host->tokenSN")));
|
||||
|
||||
if(empty($result))
|
||||
{
|
||||
dao::$errors[] = $this->lang->zanode->notFoundAgent;
|
||||
return false;
|
||||
}
|
||||
if($result->code != 'success')
|
||||
{
|
||||
dao::$errors[] = $this->lang->zanode->createVmFail;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Prepare create ZenAgent Node data. */
|
||||
$data->image = $data->image;
|
||||
$data->parent = $host->id;
|
||||
$data->mac = $result->data->mac;
|
||||
$data->vnc = (int)$result->data->vnc;
|
||||
}
|
||||
|
||||
/* Prepare create ZenAgent Node data. */
|
||||
$data->image = $data->image;
|
||||
$data->parent = $host->id;
|
||||
$data->mac = $result->data->mac;
|
||||
$data->status = static::STATUS_RUNNING;
|
||||
$data->createdBy = $this->app->user->account;
|
||||
$data->createdDate = helper::now();
|
||||
$data->vnc = (int)$result->data->vnc;
|
||||
|
||||
/* Save ZenAgent Node. */
|
||||
$this->dao->insert(TABLE_ZAHOST)->data($data)->autoCheck()->exec();
|
||||
@@ -231,6 +247,53 @@ class zanodemodel extends model
|
||||
return false;
|
||||
}
|
||||
|
||||
public function createDefaultSnapshot($zanodeID = 0)
|
||||
{
|
||||
$node = $this->getNodeByID($zanodeID);
|
||||
if($node->status != 'running') dao::$errors['name'] = $this->lang->zanode->apiError['notRunning'];
|
||||
if(dao::isError()) return false;
|
||||
|
||||
$newSnapshot = new stdClass();
|
||||
$newSnapshot->host = $node->id;
|
||||
$newSnapshot->name = "defaultSnap";
|
||||
$newSnapshot->desc = "";
|
||||
$newSnapshot->status = 'creating';
|
||||
$newSnapshot->osName = $node->osName;
|
||||
$newSnapshot->from = 'snapshot';
|
||||
$newSnapshot->createdBy = 'system';
|
||||
$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' => $newSnapshot->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')
|
||||
{
|
||||
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.
|
||||
*
|
||||
@@ -507,11 +570,11 @@ class zanodemodel extends model
|
||||
$query = str_replace('`hostID`', 't2.`id`', $query);
|
||||
}
|
||||
|
||||
$list = $this->dao->select('t1.*, t2.name as hostName, t2.extranet,t3.osName')->from(TABLE_ZAHOST)->alias('t1')
|
||||
$list = $this->dao->select("t1.*, t2.name as hostName, if(t1.type='node', t2.extranet, t1.extranet) extranet,if(t1.type='node', t3.osName, t1.osName) osName")->from(TABLE_ZAHOST)->alias('t1')
|
||||
->leftJoin(TABLE_ZAHOST)->alias('t2')->on('t1.parent = t2.id')
|
||||
->leftJoin(TABLE_IMAGE)->alias('t3')->on('t3.id = t1.image')
|
||||
->where('t1.deleted')->eq(0)
|
||||
->andWhere("t1.type")->eq("node")
|
||||
->andWhere("((t1.type = 'node' and t2.type = 'zahost') or t1.type = 'physics')")
|
||||
->beginIF($query)->andWhere($query)->fi()
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
@@ -723,14 +786,14 @@ class zanodemodel extends model
|
||||
*/
|
||||
public function getNodeByID($id)
|
||||
{
|
||||
$node = $this->dao->select('t1.*, t2.name as hostName, t2.extranet as ip,t2.zap as hzap,t3.osName, t2.tokenSN as tokenSN, t2.secret as secret')->from(TABLE_ZAHOST)
|
||||
$node = $this->dao->select("t1.*, t2.name as hostName, t2.extranet as ip,t2.zap as hzap,if(t1.type='node', t3.osName, t1.osName) osName, t2.tokenSN as tokenSN, t2.secret as secret")->from(TABLE_ZAHOST)
|
||||
->alias('t1')
|
||||
->leftJoin(TABLE_ZAHOST)->alias('t2')->on('t1.parent = t2.id')
|
||||
->leftJoin(TABLE_IMAGE)->alias('t3')->on('t3.id = t1.image')
|
||||
->where('t1.id')->eq($id)
|
||||
->fetch();
|
||||
|
||||
$host = $this->loadModel("zahost")->getByID($node->parent);
|
||||
$host = $this->loadModel("zahost")->getByID($node->type == 'node' ? $node->parent : $node->id);
|
||||
if($node->status == 'running' || $node->status == 'ready')
|
||||
{
|
||||
if(empty($host) || $host->status != 'online')
|
||||
@@ -756,7 +819,6 @@ class zanodemodel extends model
|
||||
{
|
||||
$node = $this->dao->select('*')->from(TABLE_ZAHOST)
|
||||
->where('mac')->eq($mac)
|
||||
->andWhere("type")->eq('node')
|
||||
->fetch();
|
||||
|
||||
$host = $this->loadModel("zahost")->getByID($node->parent);
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
<tr>
|
||||
<th class='c-id'><?php common::printOrderLink('t1.id', $orderBy, $vars, $lang->idAB); ?></th>
|
||||
<th class='c-name'><?php common::printOrderLink('t1.name', $orderBy, $vars, $lang->zanode->name); ?></th>
|
||||
<th class='c-type'><?php common::printOrderLink('t1.type', $orderBy, $vars, $lang->zahost->type); ?></th>
|
||||
<th class='c-ip'><?php common::printOrderLink('t1.extranet', $orderBy, $vars, $lang->zanode->extranet); ?></th>
|
||||
<th class='c-cpu'><?php common::printOrderLink('t1.cpuCores', $orderBy, $vars, $lang->zanode->cpuCores); ?></th>
|
||||
<th class='c-memory'><?php common::printOrderLink('t1.memory', $orderBy, $vars, $lang->zanode->memory); ?></th>
|
||||
@@ -68,6 +69,7 @@
|
||||
<tr>
|
||||
<td><?php echo $node->id; ?></td>
|
||||
<td title='<?php echo $node->name ?>'><?php echo html::a($this->inlink('view', "id=$node->id"), $node->name, '', ""); ?></td>
|
||||
<td><?php echo zget($this->lang->zanode->typeList, $node->type); ?></td>
|
||||
<td><?php echo $node->extranet; ?></td>
|
||||
<td><?php echo zget($config->zanode->os->cpuCores, $node->cpuCores); ?></td>
|
||||
<td><?php echo $node->memory . $this->lang->zahost->unitList['GB']; ?></td>
|
||||
@@ -78,16 +80,24 @@
|
||||
<td class='c-actions'>
|
||||
<?php
|
||||
$suspendAttr = "title='{$lang->zanode->suspend}' target='hiddenwin'";
|
||||
$suspendAttr .= $node->status != 'running' && $node->status != 'wait' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmSuspend}\")==false) return false;'";
|
||||
$suspendAttr .= $node->type == 'physics' || $node->status != 'running' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmSuspend}\")==false) return false;'";
|
||||
|
||||
$resumeAttr = "title='{$lang->zanode->resume}' target='hiddenwin'";
|
||||
$resumeAttr .= $node->status == 'running' || $node->status == 'wait' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmResume}\")==false) return false;'";
|
||||
$resumeAttr .= $node->type == 'physics' || $node->status == 'running' || $node->status == 'wait' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmResume}\")==false) return false;'";
|
||||
|
||||
$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;'";
|
||||
$rebootAttr .= $node->type == 'physics' || $node->status == 'shutoff' || $node->status == 'wait' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmReboot}\")==false) return false;'";
|
||||
|
||||
$closeAttr = "title='{$lang->zanode->shutdown}'";
|
||||
$closeAttr .= $node->type == 'physics' || $node->status == 'wait' ? ' class="btn disabled"' : ' class="btn iframe"';
|
||||
|
||||
$startAttr = "title='{$lang->zanode->boot}'";
|
||||
$startAttr .= $node->type == 'physics' || $node->status == 'wait' ? ' class="btn disabled"' : ' class="btn iframe"';
|
||||
|
||||
$snapshotAttr = "title='{$lang->zanode->createSnapshot}'";
|
||||
$snapshotAttr .= $node->status != 'running' ? ' class="btn disabled"' : ' class="btn iframe"';
|
||||
$snapshotAttr .= $node->type == 'physics' || $node->status != 'running' ? ' class="btn disabled"' : ' class="btn iframe"';
|
||||
|
||||
$imageAttr = $node->status != 'running' ? ' class="btn btn-action iframe createImage disabled"' : ' class="btn btn-action iframe createImage"';
|
||||
|
||||
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")
|
||||
@@ -101,11 +111,11 @@
|
||||
|
||||
if($node->status == "shutoff")
|
||||
{
|
||||
common::printLink('zanode', 'start', "zanodeID={$node->id}", "<i class='icon icon-play'></i> ", '', "class='btn ' title='{$lang->zanode->boot}'");
|
||||
common::printLink('zanode', 'start', "zanodeID={$node->id}", "<i class='icon icon-play'></i> ", '', $startAttr);
|
||||
}
|
||||
else
|
||||
{
|
||||
common::printLink('zanode', 'close', "zanodeID={$node->id}", "<i class='icon icon-off'></i> ", '', "class='btn ' title='{$lang->zanode->shutdown}'");
|
||||
common::printLink('zanode', 'close', "zanodeID={$node->id}", "<i class='icon icon-off'></i> ", '', $closeAttr);
|
||||
}
|
||||
|
||||
common::printLink('zanode', 'reboot', "zanodeID={$node->id}", "<i class='icon icon-restart'></i> ", '', $rebootAttr);
|
||||
@@ -117,7 +127,7 @@
|
||||
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', 'createImage', "zanodeID={$node->id}", "<i class='icon icon-export'></i> ", '', $imageAttr . " 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>";
|
||||
echo "</div>";
|
||||
|
||||
@@ -44,10 +44,20 @@
|
||||
|
||||
$deleteAttr = "title='{$lang->zanode->deleteSnapshot}' target='hiddenwin'";
|
||||
$deleteAttr .= ($snapshot->status == 'restoring' or $snapshot->status == 'creating') ? ' class="btn disabled"' : 'class="btn"';
|
||||
|
||||
$isDefalut = $snapshot->name == 'defaultSnap' && $snapshot->createdBy == 'system';
|
||||
if($isDefalut) $editAttr = $deleteAttr = 'class="btn disabled"';
|
||||
$name = $snapshot->localName ? $snapshot->localName : $snapshot->name;
|
||||
$title = $snapshot->name;
|
||||
if($snapshot->name == 'defaultSnap' && $snapshot->createdBy == 'system')
|
||||
{
|
||||
$name = $lang->zanode->snapshot->defaultSnapName;
|
||||
$title = $name;
|
||||
}
|
||||
?>
|
||||
<td title="<?php echo $snapshot->name;?>"><?php echo $snapshot->localName ? $snapshot->localName : $snapshot->name;?></td>
|
||||
<td title="<?php echo $title;?>"><?php echo $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-createdBy"><?php echo $snapshot->name == 'defaultSnap' && $snapshot->createdBy == 'system' ? $lang->zanode->snapshot->defaultSnapUser : 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);?>
|
||||
@@ -63,4 +73,3 @@
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<?php include $app->getModuleRoot() . 'common/view/footer.html.php';?>
|
||||
|
||||
@@ -22,6 +22,11 @@
|
||||
</div>
|
||||
<form method='post' target='hiddenwin' id='ajaxForm' class="load-indicator main-form form-ajax">
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th><?php echo $lang->zahost->type;?></th>
|
||||
<td><?php echo html::select('type', $lang->zanode->typeList, 'virtual', "class='form-control chosen' onchange='zahostType()'")?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->zanode->hostName;?></th>
|
||||
<td><?php echo html::select('parent', $hostPairs, $hostID, "class='form-control chosen'")?></td>
|
||||
@@ -31,6 +36,10 @@
|
||||
<th class='w-120px'><?php echo $lang->zanode->name;?></th>
|
||||
<td class='p-25f'><?php echo html::input('name', '', "class='form-control' placeholder=\"{$lang->zanode->nameValid}\"");?></td>
|
||||
</tr>
|
||||
<tr class='hidden'>
|
||||
<th class='w-120px'><?php echo $lang->zahost->IP;?></th>
|
||||
<td class='p-25f required'><?php echo html::input('extranet', '', "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->zanode->image;?></th>
|
||||
<td id="template"><?php echo html::select('image', '', '', "class='form-control chosen'")?></td>
|
||||
@@ -61,7 +70,10 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->zanode->osName;?></th>
|
||||
<td><?php echo html::input('osName', '', "class='form-control' readonly='readonly'")?></td>
|
||||
<td>
|
||||
<?php echo html::input('osName', '', "class='form-control' readonly='readonly'")?>
|
||||
<?php echo html::input('osNamePhysics', '', "class='form-control hidden'")?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->zanode->desc ?></th>
|
||||
|
||||
@@ -21,19 +21,28 @@
|
||||
</div>
|
||||
<form method='post' target='hiddenwin' id='ajaxForm' class="load-indicator main-form form-ajax">
|
||||
<table class='table table-form'>
|
||||
<?php if($zanode->type == 'node'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->zanode->hostName;?></th>
|
||||
<td class='p-25f'><?php echo html::input('', $host->name, "class='form-control' readonly='readonly'");?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th class='w-120px'><?php echo $lang->zanode->name;?></th>
|
||||
<td class='p-25f'><?php echo html::input('name', $zanode->name, "class='form-control' placeholder=\"{$lang->zanode->nameValid}\" readonly='readonly'");?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<?php if($zanode->type == 'node'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->zanode->image;?></th>
|
||||
<td class='p-25f'><?php echo html::input('', $image->name, "class='form-control' readonly='readonly'");?></td>
|
||||
</tr>
|
||||
<?php else:?>
|
||||
<tr>
|
||||
<th class='w-120px'><?php echo $lang->zahost->IP;?></th>
|
||||
<td class='p-25f'><?php echo html::input('extranet', $zanode->extranet, "class='form-control' readonly='readonly'");?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->zanode->cpuCores;?></th>
|
||||
<td class='p-25f'><?php echo html::input('', zget($config->zanode->os->cpuCores, $zanode->cpuCores), "class='form-control' readonly='readonly'");?></td>
|
||||
|
||||
@@ -44,7 +44,7 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
|
||||
<div class="col-8 main-col">
|
||||
<div class="cell">
|
||||
<div class="detail zanode-detail">
|
||||
<div class="detail-title"><?php echo $lang->zanode->view; ?></div>
|
||||
<div class="detail-title"><?php echo $lang->zahost->baseInfo; ?></div>
|
||||
<div class="detail-content article-content">
|
||||
<div class="main-row zanode-mt-8">
|
||||
<div class="col-4">
|
||||
@@ -97,11 +97,11 @@ $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 default-pwd"><?php
|
||||
<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>";
|
||||
. "<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>
|
||||
@@ -116,6 +116,10 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail zanode-detail">
|
||||
<div class="detail-title"><?php echo $lang->zanode->desc; ?></div>
|
||||
<div class="detail-content article-content"><?php echo !empty($zanode->desc) ? htmlspecialchars_decode($zanode->desc) : $lang->noData; ?></div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$canBeChanged = common::canBeChanged('zanode', $zanode);
|
||||
@@ -129,32 +133,26 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
|
||||
<button type='button' id='checkServiceStatus' class='btn btn-info'><i class="icon icon-refresh"></i> <span class='checkStatus'><?php echo $lang->zanode->init->checkStatus;?></span></button>
|
||||
</div>
|
||||
<div class="detail-content statusContainer load-indicator" id='serviceContent'>
|
||||
<div class="service-status">
|
||||
<div class="service-status hide">
|
||||
<span class='dot-symbol dot-zenagent text-danger'>●</span>
|
||||
<span> ZenAgent
|
||||
<span class="zenagent-status"><?php echo $lang->zanode->initializing; ?></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="service-status">
|
||||
<div class="service-status hide">
|
||||
<span class='dot-symbol dot-ztf text-danger'>●</span>
|
||||
<span> ZTF
|
||||
<span class="ztf-status"><?php echo $lang->zanode->initializing; ?></span>
|
||||
<a class='node-init-install hide' target='hiddenwin' href='javascript:;' data-href='<?php echo $this->createLink('zanode', 'ajaxInstallService', 'nodeID=' . $zanode->id . '&service=ztf');?>'><i class="icon icon-download icon-sm ztf-install-icon"></i><span class="ztf-install"><?php echo $lang->zanode->install ?></span></a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="status-notice">
|
||||
<div class="status-notice hide">
|
||||
<span class='init-success hide'><?php echo sprintf($lang->zanode->init->initSuccessNoticeTitle, "<a id='jumpManual' href='javascript:;'>{$lang->zanode->manual}</a>", html::a(helper::createLink('testcase', 'automation', "", '', true), $lang->zanode->automation, '', "class='iframe' title='{$lang->zanode->automation}' data-width='50%'", '')); ?></span>
|
||||
<span class='init-fail hide'><?php echo $lang->zanode->init->initFailNoticeTitle . '<br/>' . $lang->zanode->init->initFailNoticeDesc;?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell">
|
||||
<div class="detail zanode-detail">
|
||||
<div class="detail-title"><?php echo $lang->zanode->desc; ?></div>
|
||||
<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">
|
||||
@@ -177,13 +175,19 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
|
||||
<?php
|
||||
if (empty($zanode->deleted)) {
|
||||
$suspendAttr = "title='{$lang->zanode->suspend}' target='hiddenwin'";
|
||||
$suspendAttr .= $zanode->status != 'running' && $zanode->status != 'wait' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmSuspend}\")==false) return false;'";
|
||||
$suspendAttr .= $zanode->status != 'running' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmSuspend}\")==false) return false;'";
|
||||
|
||||
$resumeAttr = "title='{$lang->zanode->resume}' target='hiddenwin'";
|
||||
$resumeAttr .= $zanode->status == 'running' || $zanode->status == 'wait' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmResume}\")==false) return false;'";
|
||||
$resumeAttr .= $zanode->status == 'running' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmResume}\")==false) return false;'";
|
||||
|
||||
$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;'";
|
||||
$rebootAttr .= $zanode->status == 'shutoff' || $zanode->status == 'wait' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmReboot}\")==false) return false;'";
|
||||
|
||||
$closeAttr = "title='{$lang->zanode->shutdown}'";
|
||||
$closeAttr .= $zanode->status == 'wait' ? ' class="btn disabled"' : ' class="btn iframe"';
|
||||
|
||||
$startAttr = "title='{$lang->zanode->boot}'";
|
||||
$startAttr .= $zanode->status == 'wait' ? ' class="btn disabled"' : ' class="btn iframe"';
|
||||
|
||||
$snapshotAttr = "title='{$lang->zanode->createSnapshot}'";
|
||||
$snapshotAttr .= $zanode->status != 'running' ? ' class="btn disabled"' : ' class="btn iframe"';
|
||||
@@ -200,11 +204,11 @@ $account = strpos($zanode->osName, "windows") ? $config->zanode->defaultWinAccou
|
||||
|
||||
if($zanode->status == "shutoff")
|
||||
{
|
||||
common::printLink('zanode', 'start', "zanodeID={$zanode->id}", "<i class='icon icon-play'></i> " . $lang->zanode->bootNode, '', "title='{$lang->zanode->boot}' class='btn '");
|
||||
common::printLink('zanode', 'start', "zanodeID={$zanode->id}", "<i class='icon icon-play'></i> " . $lang->zanode->bootNode, '', $startAttr);
|
||||
}
|
||||
else
|
||||
{
|
||||
common::printLink('zanode', 'close', "zanodeID={$zanode->id}", "<i class='icon icon-off'></i> " . $lang->zanode->shutdownNode, '', "title='{$lang->zanode->shutdown}' class='btn '");
|
||||
common::printLink('zanode', 'close', "zanodeID={$zanode->id}", "<i class='icon icon-off'></i> " . $lang->zanode->shutdownNode, '', $closeAttr);
|
||||
}
|
||||
|
||||
common::printLink('zanode', 'reboot', "zanodeID={$zanode->id}", "<i class='icon icon-restart'></i> " . $lang->zanode->rebootNode, '', $rebootAttr);
|
||||
|
||||
@@ -182,4 +182,20 @@ class devTest
|
||||
$customedLang = $this->objectModel->getCustomedLang($type, $module, $method, $language);
|
||||
return empty($customedLang) ? 'null' : implode('|', $customedLang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort menus.
|
||||
*
|
||||
* @param object|array $menus
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function sortMenusTest($menus)
|
||||
{
|
||||
$result = '';
|
||||
$menus = $this->objectModel->sortMenus($menus);
|
||||
foreach($menus as $key => $value) $result .= $key . ',';
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user