Merge branch 'sprint/285' of https://gitlab.zcorp.cc/easycorp/zentaopms into sprint/285

This commit is contained in:
wangyidong
2023-02-08 16:27:17 +08:00
125 changed files with 1686 additions and 558 deletions
+1
View File
@@ -49,6 +49,7 @@ $config->action->objectNameFields['stage'] = 'name';
$config->action->objectNameFields['apistruct'] = 'name';
$config->action->objectNameFields['repo'] = 'name';
$config->action->objectNameFields['dataview'] = 'name';
$config->action->objectNameFields['zahost'] = 'name';
$config->action->objectNameFields['zanode'] = 'name';
$config->action->commonImgSize = 870;
+8
View File
@@ -237,6 +237,10 @@ $lang->action->desc->relieved = '$date, relieved by <strong>$actor</
$lang->action->desc->switchtolight = '$date, Switch from ALM mode to light mode by <strong>'. $lang->admin->system .'</strong>.' . "\n";
$lang->action->desc->getvnc = '$date, Remote control <strong>$extra</strong> by <strong>$actor</strong> .' . "\n";
$lang->action->desc->unlinkproduct = '$date, the project is disassociated from the $extra, synchronization disassociates the ' . $lang->executionCommon . 's of the project from the $extra.' . "\n";
$lang->action->desc->createdsnapshot = '$date, <strong>$actor</strong> creates a snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->restoredsnapshot = '$date, <strong>$actor</strong> restored a snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->editsnapshot = '$date, <strong>$actor</strong> edited the snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->deletesnapshot = '$date, <strong>$actor</strong> deleted snapshot <strong>$extra</strong>。' . "\n";
/* Used to describe the history of operations related to parent-child tasks. */
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> created a child task <strong>$extra</strong>。' . "\n";
@@ -419,6 +423,10 @@ $lang->action->label->switchtolight = 'switch from ALM mode to light mod
$lang->action->label->linkedrepo = 'Linked Code Repo';
$lang->action->label->unlinkedrepo = 'Unlinked Code Repo';
$lang->action->label->unlinkproduct = 'Unlinked Product';
$lang->action->label->createdsnapshot = 'create snapshot';
$lang->action->label->restoredsnapshot = 'create snapshot';
$lang->action->label->editsnapshot = 'edit snapshot';
$lang->action->label->deletesnapshot = 'deleted snapshot';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass;
+8
View File
@@ -237,6 +237,10 @@ $lang->action->desc->relieved = '$date, relieved by <strong>$actor</
$lang->action->desc->switchtolight = '$date, Switch from ALM mode to light mode by <strong>'. $lang->admin->system .'</strong>.' . "\n";
$lang->action->desc->getvnc = '$date, Remote control <strong>$extra</strong> by <strong>$actor</strong> .' . "\n";
$lang->action->desc->unlinkproduct = '$date, the project is disassociated from the $extra, synchronization disassociates the ' . $lang->executionCommon . 's of the project from the $extra.' . "\n";
$lang->action->desc->createdsnapshot = '$date, <strong>$actor</strong> creates a snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->restoredsnapshot = '$date, <strong>$actor</strong> restored a snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->editsnapshot = '$date, <strong>$actor</strong> edited the snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->deletesnapshot = '$date, <strong>$actor</strong> deleted snapshot <strong>$extra</strong>。' . "\n";
/* Used to describe the history of operations related to parent-child tasks. */
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> created a child task <strong>$extra</strong>。' . "\n";
@@ -419,6 +423,10 @@ $lang->action->label->switchtolight = 'switch from ALM mode to light mod
$lang->action->label->linkedrepo = 'Linked Code Repo';
$lang->action->label->unlinkedrepo = 'Unlinked Code Repo';
$lang->action->label->unlinkproduct = 'Unlinked Product';
$lang->action->label->createdsnapshot = 'create snapshot';
$lang->action->label->restoredsnapshot = 'create snapshot';
$lang->action->label->editsnapshot = 'edit snapshot';
$lang->action->label->deletesnapshot = 'deleted snapshot';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass;
+8
View File
@@ -237,6 +237,10 @@ $lang->action->desc->relieved = '$date, relieved by <strong>$actor</
$lang->action->desc->switchtolight = '$date, Switch from ALM mode to light mode by <strong>'. $lang->admin->system .'</strong>.' . "\n";
$lang->action->desc->getvnc = '$date, Remote control <strong>$extra</strong> by <strong>$actor</strong> .' . "\n";
$lang->action->desc->unlinkproduct = '$date, the project is disassociated from the $extra, synchronization disassociates the ' . $lang->executionCommon . 's of the project from the $extra.' . "\n";
$lang->action->desc->createdsnapshot = '$date, <strong>$actor</strong> creates a snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->restoredsnapshot = '$date, <strong>$actor</strong> restored a snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->editsnapshot = '$date, <strong>$actor</strong> edited the snapshot <strong>$extra</strong>。' . "\n";
$lang->action->desc->deletesnapshot = '$date, <strong>$actor</strong> deleted snapshot <strong>$extra</strong>。' . "\n";
/* Used to describe the history of operations related to parent-child tasks. */
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> a créé un sous-tâche <strong>$extra</strong>。' . "\n";
@@ -419,6 +423,10 @@ $lang->action->label->switchtolight = 'switch from ALM mode to light mod
$lang->action->label->linkedrepo = 'Linked Code Repo';
$lang->action->label->unlinkedrepo = 'Unlinked Code Repo';
$lang->action->label->unlinkproduct = 'Unlinked Product';
$lang->action->label->createdsnapshot = 'create snapshot';
$lang->action->label->restoredsnapshot = 'create snapshot';
$lang->action->label->editsnapshot = 'edit snapshot';
$lang->action->label->deletesnapshot = 'deleted snapshot';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass();
+8
View File
@@ -237,6 +237,10 @@ $lang->action->desc->relieved = '$date, 由 <strong>$actor</strong>
$lang->action->desc->switchtolight = '$date, 由于 <strong>'. $lang->admin->system .'</strong> 从全生命周期管理模式切换为轻量管理模式,项目访问控制由项目集内公开调整为私有。' . "\n";
$lang->action->desc->getvnc = '$date, <strong>$actor</strong>对执行节点 <strong>$extra</strong> 进行了远程操控。' . "\n";
$lang->action->desc->unlinkproduct = '$date, 系统判断由于' . $lang->executionCommon . '所属项目与$extra取消关联,同步将' . $lang->executionCommon . '与$extra取消关联。' . "\n";
$lang->action->desc->createdsnapshot = '$date, <strong>$actor</strong> 创建了快照 <strong>$extra</strong>。' . "\n";
$lang->action->desc->restoredsnapshot = '$date, <strong>$actor</strong> 还原了快照 <strong>$extra</strong>。' . "\n";
$lang->action->desc->editsnapshot = '$date, <strong>$actor</strong> 编辑了快照 <strong>$extra</strong>。' . "\n";
$lang->action->desc->deletesnapshot = '$date, <strong>$actor</strong> 删除了快照 <strong>$extra</strong>。' . "\n";
/* 用来描述和父子任务相关的操作历史记录。*/
$lang->action->desc->createchildren = '$date, 由 <strong>$actor</strong> 创建子任务 <strong>$extra</strong>。' . "\n";
@@ -419,6 +423,10 @@ $lang->action->label->switchtolight = '从全生命周期管理模式切
$lang->action->label->linkedrepo = '关联代码库到';
$lang->action->label->unlinkedrepo = '取消了项目与代码库的关联';
$lang->action->label->unlinkproduct = '取消了与产品的关联';
$lang->action->label->createdsnapshot = '创建了快照';
$lang->action->label->restoredsnapshot = '还原了快照';
$lang->action->label->editsnapshot = '编辑了快照';
$lang->action->label->deletesnapshot = '编辑了快照';
/* 动态信息按照对象分组 */
$lang->action->dynamicAction = new stdclass();
+9
View File
@@ -23,6 +23,13 @@ $config->admin->menuModuleGroup['model']['custom|required'] = array('project',
$config->admin->menuModuleGroup['feature']['custom|set'] = array('todo', 'feedback', 'user', 'block', 'story', 'task', 'bug', 'testcase', 'testtask', 'feedback', 'user');
$config->admin->menuModuleGroup['feature']['custom|required'] = array('bug', 'doc', 'product', 'story', 'productplan', 'release', 'task', 'bug', 'testcase', 'testsuite', 'testtask', 'testreport', 'caselib', 'doc', 'feedback', 'user');
$config->admin->menuModuleGroup['template']['custom|set'] = array('baseline');
if($config->vision == 'lite')
{
$config->admin->menuModuleGroup['model']['custom|set'] = array('issue', 'risk', 'opportunity', 'nc');
$config->admin->menuModuleGroup['model']['custom|required'] = array('build');
$config->admin->menuModuleGroup['feature']['custom|set'] = array('project', 'todo', 'feedback', 'user', 'block', 'story', 'task', 'bug', 'testcase', 'testtask', 'feedback', 'user');
$config->admin->menuModuleGroup['feature']['custom|required'] = array('project', 'task', 'story');
}
$config->admin->plugins[203] = new stdClass();
$config->admin->plugins[203]->name = '人力资源日历';
@@ -59,7 +66,9 @@ $config->admin->cdnRoot = 'https://cdn.easycorp.cn/web';
$config->admin->classURL = 'https://www.zentao.net/publicclass.html';
$config->admin->dynamicURL = 'https://www.zentao.net/download.html';
$config->admin->extensionURL = 'https://www.zentao.net/extension-browse.html';
$config->admin->patchURL = 'https://www.zentao.net/extension-browse-byModule-1218.html';
$config->admin->apiSite = 'https://api.zentao.net/';
$config->admin->apiSite = 'http://api.wyd.oop.cc/';
$config->admin->extAPIURL = $config->admin->apiSite . 'extension-apiGetExtensions-';
$config->admin->patchAPIURL = $config->admin->apiSite . 'extension-apiGetExtensions-bymodule-MTIxOA==-0-100-1.json';
$config->admin->downloadAPIURL = $config->admin->apiSite . 'download.json';
+2 -1
View File
@@ -37,12 +37,13 @@ class admin extends control
$hasInternet = $this->admin->checkInternet();
$clientLang = $this->app->getClientLang();
$langNotCN = common::checkNotCN();
$dateUsed = $this->admin->genDateUsed();
$this->view->title = $this->lang->admin->common;
$this->view->position[] = $this->lang->admin->index;
$this->view->plugins = $this->admin->getExtensionsByAPI('plugin', $langNotCN ? 5 : 6, $hasInternet);
$this->view->patches = $this->admin->getExtensionsByAPI('patch', 5, $hasInternet);
$this->view->usedTime = $this->admin->getUsedTime();
$this->view->dateUsed = $dateUsed;
$this->view->hasInternet = $hasInternet;
$this->view->dynamics = ($hasInternet and !$langNotCN) ? $this->admin->getDynamicsByAPI(3) : array();
$this->view->publicClass = ($hasInternet and !$langNotCN) ? $this->admin->getPublicClassByAPI(3) : array();
+20 -11
View File
@@ -4,13 +4,22 @@
.justify-between {justify-content: space-between;}
.title-color {color: #313C52}
.font-13 {font-size: 13px;}
.color-gray {color: #5E626D;}
.border-gray {border: 1px solid #E3E4E9;}
.h-56 {height: 56px;}
.h-40 {height: 40px;}
.pl-16 {padding-left: 16px;}
.px-16 {padding: 0 16px;}
.mb-16 {margin-bottom: 16px;}
.mr-16 {margin-right: 16px;}
.mx-16 {margin: 0 16px;}
.pd-3 {padding: 3px;}
.pb-3 {padding-bottom: 3px;}
.pr-4 {padding-right: 4px;}
.mt-6 {margin-top: 6px;}
.font-18 {font-size: 18px;}
.font-20 {font-size: 20px;}
.font-24 {font-size: 24px;}
.radius-4 {border-radius: 4px;}
#notice {margin: -20px -20px 20px; padding: 20px;}
#zentaoLinks {margin-top: 20px;}
@@ -19,7 +28,7 @@
.admin {display: flex; background: unset; box-shadow: none;}
.admin h4 {color: #0B0F18;}
.admin > .main {flex: 1 1 70%;}
.admin > .side {flex: 1 1 30%; padding-left: 10px; margin-left: 16px;}
.admin > .side {flex: 1 1 30%; margin-left: 16px; padding-right: 16px;}
.panel-title {padding: 10px 0px;}
.panel {padding: 0 0 0 16px;}
.settings.panel, .plug.panel {margin-bottom: 16px;}
@@ -51,7 +60,7 @@
.official-content > .title {color: #313C52; font-size: 13px; line-height: 14px;}
.classList {aspect-ratio: 4/1;}
.classList > .classItem {flex: 1 1 30%; margin: 5px; border: 1px solid rgba(227, 228, 233, 0.6); border-radius: 4px; margin-bottom: 16px; align-items: center;}
.classList > .classItem {flex: 1 1 30%; margin: 5px; border: 1px solid rgba(227, 228, 233, 0.6); border-radius: 4px; padding-bottom: 16px; align-items: center;}
.classItem > .imgBack {flex: 1 1 50%;}
.classItem > .imgBack > .classImg {background-repeat: no-repeat; background-size: contain; aspect-ratio: 16 / 9; background-position: center; margin: 0px; border-top-left-radius: 4px; border-top-right-radius: 4px;}
.classItem > .classContent {flex: 1 1 50%; padding: 5px; font-size: 14px; color: #0B0F18; text-align: center; overflow: hidden; height: 24px; margin-bottom: 6px; font-weight: 700;}
@@ -61,7 +70,6 @@
.setting-help {width: 45px; color: #9EA3B0;}
.pointer-none {pointer-events: none;}
.pd-3 {padding: 3px;}
/* css for without internet */
.main.without-internet {display: flex; flex-wrap: wrap;}
@@ -70,14 +78,15 @@
.main.without-internet > .bottom > .official.panel > .main-panel {flex-direction: row-reverse;}
/* css in side */
.time-block {background: #EDEEF2; padding: 4px; border-radius: 4px; color: #0B0F18; font-size: 15px;}
.dynamic-block {height: 64px; padding: 12px 16px; display: flex; justify-content: space-between; position: relative; line-height: 20px; border-top: 1px solid #E3E4E9;}
.dynamic-content {height: 40px; overflow: hidden;}
.dynamic-time {white-space: nowrap; position: absolute; right: 20px; bottom: 10px; padding-right: 12px; background: white;}
.time-block {background: #EDEEF2; padding:2px 4px; border-radius: 4px; color: #0B0F18; font-size: 15px; margin: 0 4px;}
.dynamic-block {height: 74px; padding: 12px 16px; display: flex; justify-content: space-between; position: relative; line-height: 20px; border-top: 1px solid #E3E4E9;}
.dynamic-content {height: 50px; line-height: 25px; overflow: hidden;}
.dynamic-time {white-space: nowrap; position: absolute; right: 12px; bottom: 10px; padding-right: 12px; background: white;}
.time-count {letter-spacing: 1px;}
.patch-block {padding: 12px 16px; line-height: 20px; border-top: 1px solid #E3E4E9;}
.patch-block {padding: 10px 16px 12px; line-height: 20px; border-top: 1px solid #E3E4E9;}
.patch-content {height: 40px; overflow: hidden;}
.upgrade-block {padding: 16px 16px; line-height: 20px; border-top: 1px solid #E3E4E9;}
.upgrade-block {padding: 6px 16px; line-height: 20px; border-top: 1px solid #E3E4E9;}
.upgrade-content {height: 20px; padding-left: 20px; position: relative; margin: 5px 0;}
.upgrade-content:before {content: ' '; width: 10px; height: 10px; background: #E3E4E9; border-radius: 50%; position: absolute; left: 0px; top: 5px;}
.upgrade-content:before {content: ' '; width: 8px; height: 8px; background: #E3E4E9; border-radius: 50%; position: absolute; left: 0px; top: 5px;}
+7 -6
View File
@@ -25,6 +25,13 @@ $lang->admin->resetPWDSetting = 'Reset password Setting';
$lang->admin->tableEngine = 'Table Engine';
$lang->admin->setModuleIndex = 'Set Module';
$lang->admin->mon = 'month';
$lang->admin->day = 'day';
$lang->admin->updateDynamics = 'updateDynamics';
$lang->admin->updatePatch = 'updatePatch';
$lang->admin->upgradeRecommend = 'upgradeRecommend';
$lang->admin->zentaoUsed = '';
$lang->admin->api = 'API';
$lang->admin->log = 'Log';
$lang->admin->setting = 'Einstellungen';
@@ -170,10 +177,4 @@ $lang->admin->menuSetting['dev']['desc'] = 'Support for secondary developm
$lang->admin->menuSetting['convert']['name'] = 'Data Import';
$lang->admin->menuSetting['convert']['desc'] = 'Data import from third-party systems.';
$lang->admin->mon = 'month';
$lang->admin->day = 'day';
$lang->admin->updateDynamics = 'updateDynamics';
$lang->admin->updatePatch = 'updatePatch';
$lang->admin->upgradeRecommend = 'upgradeRecommend';
include dirname(__FILE__) . '/menu.php';
+7 -6
View File
@@ -25,6 +25,13 @@ $lang->admin->resetPWDSetting = 'Reset password Setting';
$lang->admin->tableEngine = 'Table Engine';
$lang->admin->setModuleIndex = 'Set Module';
$lang->admin->mon = 'month';
$lang->admin->day = 'day';
$lang->admin->updateDynamics = 'updateDynamics';
$lang->admin->updatePatch = 'updatePatch';
$lang->admin->upgradeRecommend = 'upgradeRecommend';
$lang->admin->zentaoUsed = '';
$lang->admin->api = 'API';
$lang->admin->log = 'Log';
$lang->admin->setting = 'Setting';
@@ -170,10 +177,4 @@ $lang->admin->menuSetting['dev']['desc'] = 'Support for secondary developm
$lang->admin->menuSetting['convert']['name'] = 'Data Import';
$lang->admin->menuSetting['convert']['desc'] = 'Data import from third-party systems.';
$lang->admin->mon = 'month';
$lang->admin->day = 'day';
$lang->admin->updateDynamics = 'updateDynamics';
$lang->admin->updatePatch = 'updatePatch';
$lang->admin->upgradeRecommend = 'upgradeRecommend';
include dirname(__FILE__) . '/menu.php';
+7 -6
View File
@@ -25,6 +25,13 @@ $lang->admin->resetPWDSetting = 'Reset password Setting';
$lang->admin->tableEngine = 'Table Engine';
$lang->admin->setModuleIndex = 'Set Module';
$lang->admin->mon = 'month';
$lang->admin->day = 'day';
$lang->admin->updateDynamics = 'updateDynamics';
$lang->admin->updatePatch = 'updatePatch';
$lang->admin->upgradeRecommend = 'upgradeRecommend';
$lang->admin->zentaoUsed = '';
$lang->admin->api = 'API';
$lang->admin->log = 'Log';
$lang->admin->setting = 'Paramétrage';
@@ -170,10 +177,4 @@ $lang->admin->menuSetting['dev']['desc'] = 'Support for secondary developm
$lang->admin->menuSetting['convert']['name'] = 'Data Import';
$lang->admin->menuSetting['convert']['desc'] = 'Data import from third-party systems.';
$lang->admin->mon = 'month';
$lang->admin->day = 'day';
$lang->admin->updateDynamics = 'updateDynamics';
$lang->admin->updatePatch = 'updatePatch';
$lang->admin->upgradeRecommend = 'upgradeRecommend';
include dirname(__FILE__) . '/menu.php';
+31 -7
View File
@@ -83,13 +83,32 @@ $lang->admin->menuList->model['menuOrder']['5'] = 'common';
$lang->admin->menuList->model['menuOrder']['10'] = 'scrum';
$lang->admin->menuList->model['menuOrder']['15'] = 'waterfall';
$lang->admin->menuList->feature['subMenu']['my'] = array('link' => "{$lang->my->common}|custom|set|module=todo");
$lang->admin->menuList->feature['subMenu']['product'] = array('link' => "{$lang->productCommon}|custom|product|");
$lang->admin->menuList->feature['subMenu']['my'] = array('link' => "{$lang->my->common}|custom|set|module=todo", 'exclude' => 'set,required');
$lang->admin->menuList->feature['subMenu']['product'] = array('link' => "{$lang->productCommon}|custom|required|module=product|", 'exclude' => 'set,required', 'alias' => 'browsestoryconcept,product');
$lang->admin->menuList->feature['subMenu']['execution'] = array('link' => "{$lang->execution->common}|custom|execution|");
$lang->admin->menuList->feature['subMenu']['qa'] = array('link' => "{$lang->qa->common}|custom|required|module=bug");
$lang->admin->menuList->feature['subMenu']['qa'] = array('link' => "{$lang->qa->common}|custom|required|module=bug", 'exclude' => 'set,required');
$lang->admin->menuList->feature['subMenu']['kanban'] = array('link' => "{$lang->kanban->common}|custom|kanban|");
$lang->admin->menuList->feature['subMenu']['doc'] = array('link' => "{$lang->doc->common}|custom|required|module=doc");
$lang->admin->menuList->feature['subMenu']['user'] = array('link' => "{$lang->user->common}|custom|set|module=user");
$lang->admin->menuList->feature['subMenu']['doc'] = array('link' => "{$lang->doc->common}|custom|required|module=doc", 'exclude' => 'required');
$lang->admin->menuList->feature['subMenu']['user'] = array('link' => "{$lang->user->common}|custom|set|module=user", 'exclude' => 'set,required');
$lang->admin->menuList->feature['tabMenu']['my']['todo'] = array('link' => "{$lang->todo->common}|custom|set|module=todo&field=priList", 'exclude' => 'custom-set');
$lang->admin->menuList->feature['tabMenu']['my']['block'] = array('link' => "{$lang->block->common}|custom|set|module=block&field=closed", 'exclude' => 'custom-set');
if($config->vision == 'lite') $lang->admin->menuList->feature['tabMenu']['my']['task'] = array('link' => "{$lang->task->common}|custom|required|module=task", 'links' => array('custom|set|module=task&field=priList'), 'exclude' => 'custom-required,custom-set');
$lang->admin->menuList->feature['tabMenu']['product']['product'] = array('link' => "{$lang->productCommon}|custom|required|module=product", 'links' => array("custom|browsestoryconcept|", 'custom|product|'), 'alias' => 'browsestoryconcept,product', 'exclude' => 'custom-required');
$lang->admin->menuList->feature['tabMenu']['product']['story'] = array('link' => "{$lang->SRCommon}|custom|required|module=story", 'links' => array("custom|set|module=story&field=categoryList"), 'exclude' => 'custom-required,custom-set');
$lang->admin->menuList->feature['tabMenu']['product']['productplan'] = array('link' => "{$lang->productplan->shortCommon}|custom|required|module=productplan", 'exclude' => 'custom-required');
$lang->admin->menuList->feature['tabMenu']['product']['release'] = array('link' => "{$lang->release->common}|custom|required|module=release", 'exclude' => 'custom-required');
$lang->admin->menuList->feature['tabMenu']['execution']['execution'] = array('link' => "{$lang->execution->common}|custom|execution|");
$lang->admin->menuList->feature['tabMenu']['execution']['task'] = array('link' => "{$lang->task->common}|custom|required|module=task", 'links' => array('custom|set|module=task&field=priList'));
$lang->admin->menuList->feature['tabMenu']['qa']['bug'] = array('link' => "{$lang->bug->common}|custom|required|module=bug", 'links' => array("custom|set|module=bug&field=priList"), 'exclude' => 'custom-required,custom-set');
$lang->admin->menuList->feature['tabMenu']['qa']['testcase'] = array('link' => "{$lang->testcase->common}|custom|required|module=testcase", 'links' => array("custom|set|module=testcase&field=priList"), 'exclude' => 'custom-required,custom-set');
$lang->admin->menuList->feature['tabMenu']['qa']['testsuite'] = array('link' => "{$lang->testcase->testsuite}|custom|required|module=testsuite", 'exclude' => 'custom-required');
$lang->admin->menuList->feature['tabMenu']['qa']['testtask'] = array('link' => "{$lang->testtask->common}|custom|required|module=testtask", 'links' => array('custom|set|module=testtask&field=statusList'), 'exclude' => 'custom-required,custom-set');
$lang->admin->menuList->feature['tabMenu']['qa']['testreport'] = array('link' => "{$lang->testreport->common}|custom|required|module=testreport", 'exclude' => 'custom-required');
$lang->admin->menuList->feature['tabMenu']['qa']['caselib'] = array('link' => "{$lang->testcase->caselib}|custom|required|module=caselib", 'exclude' => 'custom-required');
$lang->admin->menuList->feature['menuOrder']['5'] = 'my';
$lang->admin->menuList->feature['menuOrder']['10'] = 'product';
@@ -149,10 +168,15 @@ if($config->vision == 'lite')
unset($lang->admin->menuList->feature['subMenu']['product']);
unset($lang->admin->menuList->feature['subMenu']['execution']);
unset($lang->admin->menuList->feature['subMenu']['qa']);
unset($lang->admin->menuList->feature['subMenu']['kanban']);
unset($lang->admin->menuList->feature['menuOrder']['10']);
unset($lang->admin->menuList->feature['menuOrder']['15']);
unset($lang->admin->menuList->feature['menuOrder']['20']);
unset($lang->admin->menuList->feature['menuOrder']['25']);
$lang->admin->menuList->feature['subMenu']['project'] = array('link' => "{$lang->project->common}|custom|execution|");
$lang->admin->menuList->feature['menuOrder']['15'] = 'project';
$lang->admin->menuList->feature['subMenu']['project'] = array('link' => "{$lang->projectCommon}|custom|execution|", 'exclude' => 'set,required', 'alias' => 'execution');
$lang->admin->menuList->feature['tabMenu']['project']['project'] = array('link' => "{$lang->projectCommon}|custom|required|module=project", 'exclude' => 'custom-required');
$lang->admin->menuList->feature['tabMenu']['project']['execution'] = array('link' => "{$lang->execution->common}|custom|execution|");
$lang->admin->menuList->feature['tabMenu']['project']['story'] = array('link' => "{$lang->SRCommon}|custom|required|module=story", 'links' => array("custom|set|module=story&field=priList"), 'exclude' => 'custom-required,custom-set');
$lang->admin->menuList->feature['menuOrder']['15'] = 'project';
}
+8 -1
View File
@@ -25,6 +25,13 @@ $lang->admin->resetPWDSetting = '重置密码设置';
$lang->admin->tableEngine = '表引擎';
$lang->admin->setModuleIndex = '系统功能配置';
$lang->admin->mon = '月';
$lang->admin->day = '天';
$lang->admin->updateDynamics = '更新动态';
$lang->admin->updatePatch = '补丁更新';
$lang->admin->upgradeRecommend = '推荐升级';
$lang->admin->zentaoUsed = '您已使用禅道';
$lang->admin->api = '接口';
$lang->admin->log = '日志';
$lang->admin->setting = '设置';
@@ -172,10 +179,10 @@ $lang->admin->menuSetting['convert']['desc'] = '第三方系统的数据导入
$lang->admin->mon = '月';
$lang->admin->day = '日';
$lang->admin->usedTime = '您已使用禅道';
$lang->admin->updateDynamics = '更新动态';
$lang->admin->updatePatch = '补丁更新';
$lang->admin->upgradeRecommend = '推荐升级';
$lang->admin->zentaoUsed = '您已使用禅道';
$lang->admin->openTag = '禅道';
$lang->admin->bizTag = '禅道企业版';
+131 -43
View File
@@ -269,9 +269,38 @@ class adminModel extends model
$this->setSwitcher($menuKey);
if(isset($this->lang->admin->menuList->$menuKey))
{
if(isset($this->lang->admin->menuList->$menuKey['subMenu'])) $this->lang->admin->menu = $this->lang->admin->menuList->$menuKey['subMenu'];
if(isset($this->lang->admin->menuList->$menuKey['subMenu']))
{
$moduleName = $this->app->rawModule;
$methodName = $this->app->rawMethod;
$paramName = $this->app->rawParams ? reset($this->app->rawParams) : '';
foreach($this->lang->admin->menuList->$menuKey['subMenu'] as $subMenuKey => $subMenu)
{
$subModule = '';
if($moduleName == 'custom' and strpos(',required,set,', $methodName) !== false)
{
if(strpos(',todo,block,', ",$paramName,") !== false and $subMenuKey == 'my') $subModule = 'custom';
if(strpos(',product,story,productplan,release,', ",$paramName,") !== false and $subMenuKey == 'product') $subModule = 'custom';
if(strpos(',task,', ",$paramName,") !== false and $subMenuKey == 'execution') $subModule = 'custom';
if(strpos(',project,story,', ",$paramName,") !== false and $subMenuKey == 'project') $subModule = 'custom';
if(strpos(',bug,testcase,testsuite,testtask,testreport,caselib,', ",$paramName,") !== false and $subMenuKey == 'qa') $subModule = 'custom';
if($this->config->vision == 'lite' and $paramName == 'task' and $subMenuKey == 'my') $subModule = 'custom';
}
if(!empty($subModule)) $subMenu['subModule'] = $subModule;
if(isset($this->lang->admin->menuList->$menuKey['tabMenu'][$subMenuKey]))
{
if(!empty($subModule)) $this->lang->admin->menuList->$menuKey['tabMenu'][$subMenuKey][$paramName]['subModule'] = $subModule;
$subMenu['subMenu'] = $this->lang->admin->menuList->$menuKey['tabMenu'][$subMenuKey];
}
$this->lang->admin->menu->$subMenuKey = $subMenu;
}
}
if(isset($this->lang->admin->menuList->$menuKey['menuOrder'])) $this->lang->admin->menuOrder = $this->lang->admin->menuList->$menuKey['menuOrder'];
if(isset($this->lang->admin->menuList->$menuKey['dividerMenu'])) $this->lang->admin->dividerMenu = $this->lang->admin->menuList->$menuKey['dividerMenu'];
if(isset($this->lang->admin->menuList->$menuKey['tabMenu'])) $this->lang->admin->tabMenu = $this->lang->admin->menuList->$menuKey['tabMenu'];
}
}
@@ -286,37 +315,61 @@ class adminModel extends model
$orders = array();
foreach($this->lang->admin->menuList as $menuKey => $menu)
{
$menu['disabled'] = false;
$menu['disabled'] = true;
if(!isset($menu['link'])) $menu['link'] = '';
if(!empty($menu['link']) and strpos($menu['link'], '|') !== false)
/* Set links to authorized navigation. */
if(isset($menu['subMenu']))
{
/* Check sub menu priv. */
foreach($menu['subMenu'] as $subMenuKey => $subMenu)
{
$link = array();
if(isset($menu['tabMenu'][$subMenuKey]))
{
/* Check tab menu priv. */
foreach($menu['tabMenu'][$subMenuKey] as $tabMenuKey => $tabMenu)
{
$tabMenuLink = $this->getHasPrivLink($tabMenu);
if(!empty($tabMenuLink))
{
/* Updated tertiary navigation links. */
list($module, $method, $params) = $tabMenuLink;
$tabMenuLabel = $tabMenu['link'];
$menu['tabMenu'][$subMenuKey][$tabMenuKey]['link'] = substr($tabMenuLabel, 0, strpos($tabMenuLabel, '|') + 1) . $module . '|' . $method . '|' . $params;
if(empty($link)) $link = $tabMenuLink;
}
}
}
else
{
$link = $this->getHasPrivLink($subMenu);
}
if(!empty($link))
{
/* Updated secondary navigation link. */
list($module, $method, $params) = $link;
$subMenuLabel = $subMenu['link'];
$menu['subMenu'][$subMenuKey]['link'] = substr($subMenuLabel, 0, strpos($subMenuLabel, '|') + 1) . $module . '|' . $method . '|' . $params;
/* Update the level 1 navigation link. */
if(empty($menu['link']))
{
$menu['link'] = helper::createLink($module, $method, $params);
$menu['disabled'] = false;
}
}
}
}
elseif(!empty($menu['link']) and strpos($menu['link'], '|') !== false)
{
list($module, $method) = explode('|', $menu['link']);
$menu['link'] = helper::createLink($module, $method);
if(!common::hasPriv($module, $method)) $menu['disabled'] = true;
if(common::hasPriv($module, $method)) $menu['disabled'] = false;
}
$menuOrder = isset($menu['menuOrder']) ? $menu['menuOrder'] : array();
if($menuOrder)
{
ksort($menuOrder);
/* Check sub menu priv. */
foreach($menuOrder as $subOrder => $subMenuKey)
{
list($label, $module, $method, $params) = explode('|', $menu['subMenu'][$subMenuKey]['link']);
if(!common::hasPriv($module, $method)) unset($menuOrder[$subOrder]);
}
/* Set link. */
if(!empty($menuOrder))
{
$subMenuKey = reset($menuOrder);
list($label, $module, $method, $params) = explode('|', $menu['subMenu'][$subMenuKey]['link']);
$menu['link'] = helper::createLink($module, $method, $params);
}
}
if(empty($menuOrder) and empty($menu['link'])) $menu['disabled'] = true;
$order = $menu['order'];
$orders[$order] = $menuKey;
@@ -334,6 +387,40 @@ class adminModel extends model
$this->lang->admin->menuList = $menuList;
}
/**
* Get the authorized link.
*
* @param array $menu
* @access public
* @return array
*/
public function getHasPrivLink($menu)
{
$link = array();
if(!empty($menu['link']))
{
list($label, $module, $method, $params) = explode('|', $menu['link']);
if(common::hasPriv($module, $method))
{
$link = array($module, $method, $params);
}
elseif(!empty($menu['links']))
{
foreach($menu['links'] as $menuLink)
{
list($module, $method, $params) = explode('|', $menuLink);
if(common::hasPriv($module, $method))
{
$link = array($module, $method, $params);
break;
}
}
}
}
return $link;
}
/**
* Get menu key
*
@@ -523,23 +610,6 @@ class adminModel extends model
return $downloads;
}
/**
* Get used time for this account.
*
* @access public
* @return array
*/
public function getUsedTime()
{
$firstDate = $this->dao->select('id,date')->from(TABLE_ACTION)->where('actor')->eq($this->app->user->account)->orderBy('`date`')->limit(1)->fetch('date');
$days = helper::diffDate(helper::now(), $firstDate);
$year = floor($days / 365);
$days = $days % 365;
$month = floor($days / 30);
$days = $days % 30;
return array('year' => $year, 'month' => $month, 'day' => $days);
}
/**
* Check internet.
*
@@ -560,4 +630,22 @@ class adminModel extends model
return (bool)$connected;
}
/**
* Get date used object.
*
* @access public
* @return object
*/
public function genDateUsed()
{
$firstUseDate = $this->dao->select('date')->from(TABLE_ACTION)
->where('date')->gt('0000-00-00')
->andWhere('actor')->eq($this->app->user->account)
->orderBy('date_asc')
->limit('1')
->fetch('date');
return helper::getDateInterval($firstUseDate);
}
}
+29 -27
View File
@@ -15,7 +15,7 @@
<div id='mainContent' class='main-content admin'>
<div class="main <?php if(!$hasInternet) echo 'without-internet';?>">
<div class="settings panel">
<div class="panel-title"><?php echo $lang->admin->setting?></div>
<div class="panel-title mt-6"><?php echo $lang->admin->setting?></div>
<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;?>
@@ -87,67 +87,69 @@
</div>
<?php if($hasInternet and !$langNotCN):?>
<div class="side panel">
<div class="side panel" style="background: #FCFDFE">
<div class="h-56 flex align-center justify-between">
<div class="panel-title"><?php echo $lang->admin->zentaoInfo?></div>
<div class="time-count color-gray">
<?php echo $lang->admin->usedTime;?>
<?php if($usedTime['year']) echo "<span class='time-block'>{$usedTime['year']}</span>{$lang->year}";?>
<?php if($usedTime['month']) echo "<span class='time-block'>{$usedTime['month']}</span>{$lang->admin->mon}";?>
<?php if($usedTime['day']) echo "<span class='time-block'>{$usedTime['day']}</span>{$lang->admin->day}";?>
<div class="time-count">
<?php echo $lang->admin->zentaoUsed;?>
<?php if($dateUsed->year):?>
<span class="time-block"><?php echo $dateUsed->year;?></span><?php echo $lang->year;?>
<?php endif;?>
<?php if($dateUsed->month):?>
<span class="time-block"><?php echo $dateUsed->month;?></span><?php echo $lang->admin->mon;?>
<?php endif;?>
<span class="time-block"><?php echo $dateUsed->day;?></span><?php echo $lang->admin->day;?>
</div>
</div>
<div class="border-gray mb-16">
<div class="border-gray mb-16 radius-4">
<div class="h-40 pl-16 flex align-center justify-between">
<div class="panel-title"><?php echo $lang->admin->updateDynamics?></div>
<?php echo html::a($config->admin->dynamicURL, "{$lang->more} <i class='icon icon-caret-right'></i>", '_blank', 'class="more text-muted flex align-center"');?>
<?php echo html::a($config->admin->dynamicURL, "{$lang->more} <i class='icon icon-caret-right pb-3'></i>", '_blank', 'class="more text-muted flex align-center"');?>
</div>
<?php foreach($dynamics as $dynamic):?>
<div class="dynamic-block">
<div class="dynamic-content"><i class="icon icon-horn text-primary"></i><?php echo html::a($dynamic->link, $dynamic->title, '_blank');?></div>
<div class="dynamic-content"><i class="icon icon-horn text-primary pr-4 font-20"></i><?php echo html::a($dynamic->link, $dynamic->title, '_blank');?></div>
<div class="dynamic-time"><?php echo substr($dynamic->addedDate, 0, 10);?></div>
</div>
<?php endforeach;?>
</div>
<div class="border-gray mb-16">
<div class="border-gray mb-16 radius-4">
<div class="h-40 pl-16 flex align-center justify-between">
<div class="panel-title"><?php echo $lang->admin->updatePatch?></div>
<?php echo html::a($config->admin->extensionURL, "{$lang->more} <i class='icon icon-caret-right'></i>", '_blank', 'class="more text-muted flex align-center"');?>
<?php echo html::a($config->admin->patchURL, "{$lang->more} <i class='icon icon-caret-right pb-3'></i>", '_blank', 'class="more text-muted flex align-center"');?>
</div>
<?php foreach($patches as $patch):?>
<div class="patch-block">
<div class="title flex justify-between">
<div class="panel-title"><?php echo $patch->name?></div>
<div class="title flex justify-between">
<div class="panel-title"><?php echo $patch->name?></div>
<a href="<?php echo $patch->viewLink;?>" class='ext-download flex align-center' target='_blank'><i class='icon icon-download-alt text-primary bg-primary-100 pd-3'></i></a>
</div>
<div class="patch-content color-gray">
<?php echo $patch->desc?>
</div>
<div class="patch-content"><?php echo $patch->desc?></div>
</div>
<?php endforeach;?>
</div>
<?php if($config->edition != 'max'):?>
<div class="border-gray mb-16">
<div class="border-gray mb-16 radius-4">
<div class="h-40 pl-16 flex align-center justify-between">
<div class="panel-title"><?php echo $lang->admin->upgradeRecommend?></div>
<?php echo html::a($config->admin->apiRoot, "{$lang->more} <i class='icon icon-caret-right'></i>", '_blank', 'class="more text-muted flex align-center"');?>
<?php echo html::a($config->admin->apiRoot, "{$lang->more} <i class='icon icon-caret-right pb-3'></i>", '_blank', 'class="more text-muted flex align-center"');?>
</div>
<?php if($config->edition != 'biz'):?>
<div class="upgrade-block">
<div class="title text-primary flex justify-between">
<div><?php echo $lang->admin->bizTag?></div>
<div class="flex align-center"><div><?php echo html::a($lang->admin->bizInfoURL, $lang->admin->productDetail, '_blank', "class='text-primary'");?></div><i class="icon icon-caret-right text-primary"></i></div>
</div>
<a class="title text-primary flex justify-between" href="<?php echo $lang->admin->bizInfoURL;?>" target="_blank">
<div class="panel-title"><i class="icon icon-zentao text-primary pr-4 font-18"></i><?php echo $lang->admin->bizTag?></div>
<div class="flex align-center"><div><?php echo $lang->admin->productDetail?></div><i class="icon icon-caret-right text-primary pb-3"></i></div>
</a>
<?php foreach($lang->admin->productFeature['biz'] as $feature):?>
<div class="upgrade-content color-gray"><?php echo $feature;?></div>
<?php endforeach;?>
</div>
<?php endif;?>
<div class="upgrade-block">
<div class="title text-primary flex justify-between">
<div><?php echo $lang->admin->maxTag?></div>
<div class="flex align-center"><div><?php echo html::a($lang->admin->maxInfoURL, $lang->admin->productDetail, '_blank', "class='text-primary'");?></div><i class="icon icon-caret-right text-primary"></i></div>
</div>
<a class="title text-primary flex justify-between" href='<?php echo $lang->admin->maxInfoURL;?>' target="_blank">
<div class="panel-title"><i class="icon icon-zentao text-primary pr-4 font-18"></i><?php echo $lang->admin->maxTag?></div>
<div class="flex align-center"><div><?php echo $lang->admin->productDetail?></div><i class="icon icon-caret-right text-primary pb-3"></i></div>
</a>
<?php foreach($lang->admin->productFeature['max'] as $feature):?>
<div class="upgrade-content color-gray"><?php echo $feature;?></div>
<?php endforeach;?>
-2
View File
@@ -10,8 +10,6 @@
* @link http://www.zentao.net
*/
global $config;
$lang->block = new stdclass();
$lang->block->common = 'InfoBlock';
$lang->block->id = 'ID';
$lang->block->params = 'Params';
$lang->block->name = 'Name';
-2
View File
@@ -10,8 +10,6 @@
* @link http://www.zentao.net
*/
global $config;
$lang->block = new stdclass();
$lang->block->common = 'Block';
$lang->block->id = 'ID';
$lang->block->params = 'Params';
$lang->block->name = 'Name';
-2
View File
@@ -10,8 +10,6 @@
* @link http://www.zentao.net
*/
global $config;
$lang->block = new stdclass();
$lang->block->common = 'Bloc';
$lang->block->id = 'ID';
$lang->block->params = 'Params';
$lang->block->name = 'Nom';
-2
View File
@@ -10,8 +10,6 @@
* @link http://www.zentao.net
*/
global $config;
$lang->block = new stdclass();
$lang->block->common = 'Block';
$lang->block->name = 'Tên';
$lang->block->style = 'Kiểu';
$lang->block->grid = 'Vị trí';
-2
View File
@@ -10,8 +10,6 @@
* @link http://www.zentao.net
*/
global $config;
$lang->block = new stdclass();
$lang->block->common = '区块';
$lang->block->id = '编号';
$lang->block->params = '参数';
$lang->block->name = '区块名称';
+2
View File
@@ -46,6 +46,8 @@
.minw-80px {min-width: 80px;}
.title-group.required:after {display: none;}
.title-group.required > .required:after {display: block; right: 29px; top: 5px;}
#titleBox.required:after{display: block; right: 29px; top: 5px;}
#priRequiredBox.required:after{display: block; right: -12px; top: 5px;}
.pri-selector > .btn {padding: 5px 8px !important; width: 100%;}
.pri-selector > .dropdown-menu {padding: 10px;}
+5 -5
View File
@@ -25,13 +25,13 @@
<thead>
<tr class='text-center'>
<th class='c-id'><?php echo $lang->idAB;?></th>
<th class='c-module<?php echo strpos($config->testcase->create->requiredFields, 'module') ? ' required' : '';?>'><?php echo $lang->testcase->module;?></th>
<th class='c-module<?php echo strpos($config->testcase->create->requiredFields, 'module') !== false ? ' required' : '';?>'><?php echo $lang->testcase->module;?></th>
<th class='required'><?php echo $lang->testcase->title;?></th>
<th class='c-status required'><?php echo $lang->testcase->type;?></th>
<th class='c-status'><?php echo $lang->testcase->pri;?></th>
<th class='c-text'><?php echo $lang->testcase->precondition;?></th>
<th class='c-text'><?php echo $lang->testcase->keywords;?></th>
<th class='c-text'><?php echo $lang->testcase->stage;?></th>
<th class='c-status<?php echo strpos($config->testcase->create->requiredFields, 'pri') !== false ? ' required' : '';?>'><?php echo $lang->testcase->pri;?></th>
<th class='c-text<?php echo strpos($config->testcase->create->requiredFields, 'precondition') !== false ? ' required' : '';?>'><?php echo $lang->testcase->precondition;?></th>
<th class='c-text<?php echo strpos($config->testcase->create->requiredFields, 'keywords') !== false ? ' required' : '';?>'><?php echo $lang->testcase->keywords;?></th>
<th class='c-text<?php echo strpos($config->testcase->create->requiredFields, 'stage') !== false ? ' required' : '';?>'><?php echo $lang->testcase->stage;?></th>
</tr>
</thead>
<tbody>
+7 -6
View File
@@ -33,7 +33,7 @@
<?php echo html::select('lib', $libraries, $libID, "onchange='loadLibModules(this.value);' class='form-control chosen'");?>
</div>
</td>
<td style='padding-left:15px;'<?php echo strpos($config->testcase->create->requiredFields, 'module') ? ' class="required"' : '';?>>
<td style='padding-left:15px;'<?php echo strpos($config->testcase->create->requiredFields, 'module') !== false ? ' class="required"' : '';?>>
<div class='input-group' id='moduleIdBox'>
<span class="input-group-addon w-80px"><?php echo $lang->testcase->module?></span>
<?php
@@ -55,7 +55,7 @@
<th><?php echo $lang->testcase->type;?></th>
<td><?php echo html::select('type', $lang->testcase->typeList, $type, "class='form-control chosen'");?></td>
<?php if(strpos(",$showFields,", 'stage') !== false):?>
<td style='padding-left:15px'>
<td style='padding-left:15px'<?php echo strpos($config->testcase->create->requiredFields, 'stage') !== false ? ' class="required"' : '';?>>
<div class='input-group'>
<span class='input-group-addon w-80px'><?php echo $lang->testcase->stage?></span>
<?php echo html::select('stage[]', $lang->testcase->stageList, $stage, "class='form-control chosen' multiple='multiple'");?>
@@ -67,7 +67,7 @@
<th><?php echo $lang->testcase->title;?></th>
<td colspan='2'>
<div class="input-group title-group">
<div class="input-control has-icon-right">
<div id="titleBox" class="input-control has-icon-right">
<?php echo html::input('title', $caseTitle, "class='form-control'");?>
<div class="colorpicker">
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown"><span class="cp-title"></span><span class="color-bar"></span><i class="ic"></i></button>
@@ -101,7 +101,8 @@
<?php echo html::select('pri', (array)$priList, $pri, "class='form-control'");?>
<?php else: ?>
<?php ksort($priList);?>
<div class="input-group-btn pri-selector" data-type="pri">
<?php $hasPri = strpos($config->testcase->create->requiredFields, 'pri') !== false ? True : False;?>
<div <?php echo $hasPri ? "id='priRequiredBox'" : '';?> class="input-group-btn pri-selector <?php echo $hasPri ? 'required' : '';?>" data-type="pri">
<button type="button" class="btn dropdown-toggle br-0" data-toggle="dropdown">
<span class="pri-text"><span class="label-pri label-pri-<?php echo empty($pri) ? '0' : $pri?>" title="<?php echo $pri?>"><?php echo $pri?></span></span> &nbsp;<span class="caret"></span>
</button>
@@ -116,7 +117,7 @@
</tr>
<tr>
<th><?php echo $lang->testcase->precondition;?></th>
<td colspan='2'><?php echo html::textarea('precondition', $precondition, " rows='2' class='form-control'");?></td>
<td colspan='2' <?php echo strpos($config->testcase->create->requiredFields, 'precondition') !== false ? ' class="required"' : '';?>><?php echo html::textarea('precondition', $precondition, " rows='2' class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->testcase->steps;?></th>
@@ -189,7 +190,7 @@
<?php if(strpos(",$showFields,", ',keywords,') !== false):?>
<tr>
<th><?php echo $lang->testcase->keywords;?></th>
<td colspan='2'><?php echo html::input('keywords', '', "class='form-control'");?></td>
<td colspan='2' <?php echo strpos($config->testcase->create->requiredFields, 'keywords') !== false ? ' class="required"' : '';?>><?php echo html::input('keywords', '', "class='form-control'");?></td>
</tr>
<?php endif;?>
<tr>
+1
View File
@@ -3,6 +3,7 @@ $lang->common = new stdclass();
$lang->index = new stdclass();
$lang->my = new stdclass();
$lang->todo = new stdclass();
$lang->block = new stdclass();
$lang->program = new stdclass();
$lang->programplan = new stdclass();
$lang->product = new stdclass();
+2
View File
@@ -158,6 +158,8 @@ $lang->delayed = 'Delayed';
$lang->common->common = 'Standard Module';
$lang->common->story = 'Story';
$lang->my->common = 'My';
$lang->todo->common = 'Todo';
$lang->block->common = 'InfoBlock';
$lang->program->common = 'Program';
$lang->product->common = 'Product';
$lang->project->common = 'Project';
+2
View File
@@ -158,6 +158,8 @@ $lang->delayed = 'Delayed';
$lang->common->common = 'Common Module';
$lang->common->story = 'Story';
$lang->my->common = 'My';
$lang->todo->common = 'Todo';
$lang->block->common = 'Block';
$lang->program->common = 'Program';
$lang->product->common = 'Product';
$lang->project->common = 'Project';
+2
View File
@@ -158,6 +158,8 @@ $lang->delayed = 'Delayed';
$lang->common->common = 'Module Commun';
$lang->common->story = 'Story';
$lang->my->common = 'My';
$lang->todo->common = 'Agenda';
$lang->block->common = 'Bloc';
$lang->program->common = 'Program';
$lang->product->common = 'Product';
$lang->project->common = 'Project';
+2
View File
@@ -158,6 +158,8 @@ $lang->delayed = '已延期';
$lang->common->common = '公有模块';
$lang->common->story = '需求';
$lang->my->common = '地盘';
$lang->todo->common = '待办';
$lang->block->common = '区块';
$lang->program->common = '项目集';
$lang->product->common = '产品';
$lang->project->common = '项目';
+4 -1
View File
@@ -1343,7 +1343,9 @@ class commonModel extends model
$alias = isset($menuItem->alias) ? $menuItem->alias : '';
$subModule = isset($menuItem->subModule) ? explode(',', $menuItem->subModule) : array();
$class = isset($menuItem->class) ? $menuItem->class : '';
$exclude = isset($menuItem->exclude) ? $menuItem->exclude : '';
$active = '';
if($subModule and in_array($currentModule, $subModule)) $active = 'active';
// if($alias and $moduleName == $currentModule and strpos(",$alias,", ",$currentMethod,") !== false) $active = 'active';
if($menuItem->link)
@@ -1358,7 +1360,8 @@ class commonModel extends model
if(isset($menuItem->link['module'])) $module = $menuItem->link['module'];
if(isset($menuItem->link['method'])) $method = $menuItem->link['method'];
}
if($module == $currentModule and ($method == $currentMethod or strpos(",$alias,", ",$currentMethod,") !== false)) $active = 'active';
if($module == $currentModule and (($method == $currentMethod and strpos(",$exclude,", ",$currentModule-$currentMethod,") === false) or strpos(",$alias,", ",$currentMethod,") !== false)) $active = 'active';
$label = $menuItem->text;
$dropMenu = '';
+2 -1
View File
@@ -29,7 +29,8 @@ include 'chosen.html.php';
</div>
</div>
<?php if(isset($lang->{$app->tab}->menu->$activeMenu) and is_array($lang->{$app->tab}->menu->$activeMenu) and isset($lang->{$app->tab}->menu->{$activeMenu}['subMenu'])):?>
<div id='subHeader'>
<?php $subMenuClass = $app->tab == 'admin' ? 'admin-tab-menu' : '';?>
<div id='subHeader' class="<?php echo $subMenuClass;?>">
<div class='container'>
<div id="pageNav" class='btn-toolbar'><?php if(isset($lang->modulePageNav)) echo $lang->modulePageNav;?></div>
<nav id='subNavbar'><?php common::printModuleMenu($activeMenu);?></nav>
+2
View File
@@ -70,3 +70,5 @@ $config->custom->fieldList['testtask'] = 'owner,pri,desc';
$config->custom->fieldList['doc'] = 'keywords,content';
$config->custom->fieldList['user']['create'] = 'dept,role,email,commiter';
$config->custom->fieldList['user']['edit'] = 'dept,role,email,commiter,skype,qq,mobile,phone,address,zipcode,dingding,slack,whatsapp,weixin';
$config->custom->notSetMethods = array('required', 'browsestoryconcept', 'product');
+4 -2
View File
@@ -382,7 +382,7 @@ class custom extends control
$this->view->position[] = $this->lang->custom->required;
$this->view->requiredFields = $requiredFields;
$this->view->moduleName = $moduleName;
$this->view->module = $moduleName;
$this->display();
}
@@ -439,6 +439,7 @@ class custom extends control
$this->view->title = $this->lang->custom->browseStoryConcept;
$this->view->position[] = $this->lang->custom->browseStoryConcept;
$this->view->URSRList = $this->custom->getURSRList();
$this->view->module = 'product';
$this->display();
}
@@ -576,9 +577,10 @@ class custom extends control
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'reload'));
}
$this->view->title = $this->lang->custom->product;
$this->view->title = $this->lang->custom->productName;
$this->view->position[] = $this->lang->custom->common;
$this->view->position[] = $this->view->title;
$this->view->module = 'product';
$this->display();
}
+2
View File
@@ -1 +1,3 @@
.table-form>tbody>tr>th{text-align: center}
.c-default {width: 70px;}
.setBtn {margin-top: -5px;}
-6
View File
@@ -8,12 +8,6 @@ function delItem(clickedButton)
$(clickedButton).parent().parent().remove();
}
$(function()
{
$('#' + module + 'Tab').addClass('btn-active-text');
$('#' + field + 'Tab').addClass('active');
})
$('[name*=unitList]').change(function()
{
var defaultCurrency = $('#defaultCurrency').val();
+38 -17
View File
@@ -22,7 +22,7 @@ $lang->custom->score = 'Score';
$lang->custom->timezone = 'Timezone';
$lang->custom->scoreReset = 'Reset Score';
$lang->custom->scoreTitle = 'Point Feature';
$lang->custom->product = $lang->productCommon;
$lang->custom->productName = $lang->productCommon;
$lang->custom->convertFactor = 'Convert factor';
$lang->custom->region = 'Interval';
$lang->custom->tips = 'Tips';
@@ -89,21 +89,26 @@ $lang->custom->closedExecution = 'Closed ' . $lang->executionCommon;
$lang->custom->closedKanban = 'Closed ' . $lang->custom->kanban;
$lang->custom->closedProduct = 'Closed ' . $lang->productCommon;
$lang->custom->object['project'] = 'Project';
$lang->custom->object['product'] = $lang->productCommon;
$lang->custom->object['execution'] = $lang->custom->execution;
$lang->custom->object['kanban'] = $lang->custom->kanban;
$lang->custom->object['story'] = 'Story';
$lang->custom->object['task'] = 'Task';
$lang->custom->object['bug'] = 'Bug';
$lang->custom->object['testcase'] = 'Case';
$lang->custom->object['testtask'] = 'Build';
$lang->custom->object['todo'] = 'Todo';
$lang->custom->object['user'] = 'User';
$lang->custom->object['block'] = 'ClosedBlock';
$lang->custom->object['flow'] = 'Flow';
$lang->custom->object['score'] = 'Score';
$lang->custom->object['mode'] = 'Mode';
$lang->custom->object['project'] = 'Project';
$lang->custom->object['product'] = $lang->productCommon;
$lang->custom->object['execution'] = $lang->custom->execution;
$lang->custom->object['kanban'] = $lang->custom->kanban;
$lang->custom->object['story'] = 'Story';
$lang->custom->object['task'] = 'Task';
$lang->custom->object['bug'] = 'Bug';
$lang->custom->object['testcase'] = 'Case';
$lang->custom->object['testtask'] = 'Build';
$lang->custom->object['todo'] = 'Todo';
$lang->custom->object['user'] = 'User';
$lang->custom->object['block'] = 'ClosedBlock';
$lang->custom->object['flow'] = 'Flow';
$lang->custom->object['score'] = 'Score';
$lang->custom->object['mode'] = 'Mode';
$lang->custom->object['productplan'] = 'Plan';
$lang->custom->object['release'] = 'Release';
$lang->custom->object['testsuite'] = 'Test Suite';
$lang->custom->object['testreport'] = 'Test Report';
$lang->custom->object['caselib'] = 'Case Library';
$lang->custom->menuOrder[5] = 'project';
$lang->custom->menuOrder[10] = 'product';
@@ -129,9 +134,16 @@ $lang->custom->block->fields['closed'] = 'Closed Block';
$lang->custom->project = new stdClass();
$lang->custom->project->currencySetting = 'Currency Setting';
$lang->custom->project->defaultCurrency = 'Default Currency';
$lang->custom->project->fields['required'] = $lang->custom->required;
$lang->custom->project->fields['unitList'] = 'Unit List';
$lang->custom->product = new stdClass();
$lang->custom->product->fields['required'] = $lang->custom->required;
$lang->custom->product->fields['browsestoryconcept'] = 'Story Concpet';
$lang->custom->product->fields['product'] = 'Close Setting';
$lang->custom->story = new stdClass();
$lang->custom->story->fields['required'] = $lang->custom->required;
$lang->custom->story->fields['categoryList'] = 'Category';
$lang->custom->story->fields['priList'] = 'Priority';
$lang->custom->story->fields['sourceList'] = 'Source';
@@ -143,13 +155,14 @@ $lang->custom->story->fields['reviewResultList'] = 'Review Result';
$lang->custom->story->fields['review'] = 'Review Required';
$lang->custom->task = new stdClass();
$lang->custom->task->fields['required'] = $lang->custom->required;
$lang->custom->task->fields['priList'] = 'Priority';
$lang->custom->task->fields['typeList'] = 'Type';
$lang->custom->task->fields['reasonList'] = 'Close Reason';
$lang->custom->task->fields['statusList'] = 'Status';
$lang->custom->task->fields['hours'] = 'Mannstunden';
$lang->custom->bug = new stdClass();
$lang->custom->bug->fields['required'] = $lang->custom->required;
$lang->custom->bug->fields['priList'] = 'Priority';
$lang->custom->bug->fields['severityList'] = 'Severity';
$lang->custom->bug->fields['osList'] = 'OS';
@@ -160,6 +173,7 @@ $lang->custom->bug->fields['statusList'] = 'Status';
$lang->custom->bug->fields['longlife'] = 'Stalled Days';
$lang->custom->testcase = new stdClass();
$lang->custom->testcase->fields['required'] = $lang->custom->required;
$lang->custom->testcase->fields['priList'] = 'Priority';
$lang->custom->testcase->fields['typeList'] = 'Type';
$lang->custom->testcase->fields['stageList'] = 'Phase';
@@ -168,10 +182,17 @@ $lang->custom->testcase->fields['statusList'] = 'Status';
$lang->custom->testcase->fields['review'] = 'Review Required';
$lang->custom->testtask = new stdClass();
$lang->custom->testtask->fields['required'] = $lang->custom->required;
$lang->custom->testtask->fields['statusList'] = 'Status';
$lang->custom->testtask->fields['typeList'] = 'Type';
$lang->custom->testtask->fields['priList'] = 'Priority';
$lang->custom->testreport = new stdClass();
$lang->custom->testreport->fields['required'] = $lang->custom->required;
$lang->custom->caselib = new stdClass();
$lang->custom->caselib->fields['required'] = $lang->custom->required;
$lang->custom->todo = new stdClass();
$lang->custom->todo->fields['priList'] = 'Priority';
$lang->custom->todo->fields['typeList'] = 'Type';
+38 -17
View File
@@ -22,7 +22,7 @@ $lang->custom->score = 'Point';
$lang->custom->timezone = 'Timezone';
$lang->custom->scoreReset = 'Reset Points';
$lang->custom->scoreTitle = 'Point Feature';
$lang->custom->product = $lang->productCommon;
$lang->custom->productName = $lang->productCommon;
$lang->custom->convertFactor = 'Convert factor';
$lang->custom->region = 'Interval';
$lang->custom->tips = 'Tips';
@@ -89,21 +89,26 @@ $lang->custom->closedExecution = 'Closed ' . $lang->executionCommon;
$lang->custom->closedKanban = 'Closed ' . $lang->custom->kanban;
$lang->custom->closedProduct = 'Closed ' . $lang->productCommon;
$lang->custom->object['project'] = 'Project';
$lang->custom->object['product'] = $lang->productCommon;
$lang->custom->object['execution'] = $lang->custom->execution;
$lang->custom->object['kanban'] = $lang->custom->kanban;
$lang->custom->object['story'] = 'Story';
$lang->custom->object['task'] = 'Task';
$lang->custom->object['bug'] = 'Bug';
$lang->custom->object['testcase'] = 'Case';
$lang->custom->object['testtask'] = 'Request';
$lang->custom->object['todo'] = 'Todo';
$lang->custom->object['user'] = 'User';
$lang->custom->object['block'] = 'Block';
$lang->custom->object['flow'] = 'Flow';
$lang->custom->object['score'] = 'Score';
$lang->custom->object['mode'] = 'Mode';
$lang->custom->object['project'] = 'Project';
$lang->custom->object['product'] = $lang->productCommon;
$lang->custom->object['execution'] = $lang->custom->execution;
$lang->custom->object['kanban'] = $lang->custom->kanban;
$lang->custom->object['story'] = 'Story';
$lang->custom->object['task'] = 'Task';
$lang->custom->object['bug'] = 'Bug';
$lang->custom->object['testcase'] = 'Case';
$lang->custom->object['testtask'] = 'Request';
$lang->custom->object['todo'] = 'Todo';
$lang->custom->object['user'] = 'User';
$lang->custom->object['block'] = 'Block';
$lang->custom->object['flow'] = 'Flow';
$lang->custom->object['score'] = 'Score';
$lang->custom->object['mode'] = 'Mode';
$lang->custom->object['productplan'] = 'Plan';
$lang->custom->object['release'] = 'Release';
$lang->custom->object['testsuite'] = 'Test Suite';
$lang->custom->object['testreport'] = 'Test Report';
$lang->custom->object['caselib'] = 'Case Library';
$lang->custom->menuOrder[5] = 'project';
$lang->custom->menuOrder[10] = 'product';
@@ -129,9 +134,16 @@ $lang->custom->block->fields['closed'] = 'Closed Block';
$lang->custom->project = new stdClass();
$lang->custom->project->currencySetting = 'Currency Setting';
$lang->custom->project->defaultCurrency = 'Default Currency';
$lang->custom->project->fields['required'] = $lang->custom->required;
$lang->custom->project->fields['unitList'] = 'Unit List';
$lang->custom->product = new stdClass();
$lang->custom->product->fields['required'] = $lang->custom->required;
$lang->custom->product->fields['browsestoryconcept'] = 'Story Concpet';
$lang->custom->product->fields['product'] = 'Close Setting';
$lang->custom->story = new stdClass();
$lang->custom->story->fields['required'] = $lang->custom->required;
$lang->custom->story->fields['categoryList'] = 'Category';
$lang->custom->story->fields['priList'] = 'Priority';
$lang->custom->story->fields['sourceList'] = 'Source';
@@ -143,13 +155,14 @@ $lang->custom->story->fields['reviewResultList'] = 'Review Result';
$lang->custom->story->fields['review'] = 'Need Review';
$lang->custom->task = new stdClass();
$lang->custom->task->fields['required'] = $lang->custom->required;
$lang->custom->task->fields['priList'] = 'Priority';
$lang->custom->task->fields['typeList'] = 'Type';
$lang->custom->task->fields['reasonList'] = 'Close Reason';
$lang->custom->task->fields['statusList'] = 'Status';
$lang->custom->task->fields['hours'] = 'Effort';
$lang->custom->bug = new stdClass();
$lang->custom->bug->fields['required'] = $lang->custom->required;
$lang->custom->bug->fields['priList'] = 'Priority';
$lang->custom->bug->fields['severityList'] = 'Severity';
$lang->custom->bug->fields['osList'] = 'OS';
@@ -160,6 +173,7 @@ $lang->custom->bug->fields['statusList'] = 'Status';
$lang->custom->bug->fields['longlife'] = 'Stalled Days';
$lang->custom->testcase = new stdClass();
$lang->custom->testcase->fields['required'] = $lang->custom->required;
$lang->custom->testcase->fields['priList'] = 'Priority';
$lang->custom->testcase->fields['typeList'] = 'Type';
$lang->custom->testcase->fields['stageList'] = 'Phase';
@@ -168,10 +182,17 @@ $lang->custom->testcase->fields['statusList'] = 'Status';
$lang->custom->testcase->fields['review'] = 'Need Review';
$lang->custom->testtask = new stdClass();
$lang->custom->testtask->fields['required'] = $lang->custom->required;
$lang->custom->testtask->fields['statusList'] = 'Status';
$lang->custom->testtask->fields['typeList'] = 'Type';
$lang->custom->testtask->fields['priList'] = 'Priority';
$lang->custom->testreport = new stdClass();
$lang->custom->testreport->fields['required'] = $lang->custom->required;
$lang->custom->caselib = new stdClass();
$lang->custom->caselib->fields['required'] = $lang->custom->required;
$lang->custom->todo = new stdClass();
$lang->custom->todo->fields['priList'] = 'Priority';
$lang->custom->todo->fields['typeList'] = 'Type';
+38 -17
View File
@@ -22,7 +22,7 @@ $lang->custom->score = 'Point';
$lang->custom->timezone = 'Timezone';
$lang->custom->scoreReset = 'Réinit Points';
$lang->custom->scoreTitle = 'Fonctionnalité des Points';
$lang->custom->product = $lang->productCommon;
$lang->custom->productName = $lang->productCommon;
$lang->custom->convertFactor = 'Convert factor';
$lang->custom->region = 'Interval';
$lang->custom->tips = 'Tips';
@@ -89,21 +89,26 @@ $lang->custom->closedExecution = 'Closed ' . $lang->executionCommon;
$lang->custom->closedKanban = 'Closed ' . $lang->custom->kanban;
$lang->custom->closedProduct = 'Closed ' . $lang->productCommon;
$lang->custom->object['project'] = 'Project';
$lang->custom->object['product'] = $lang->productCommon;
$lang->custom->object['execution'] = $lang->custom->execution;
$lang->custom->object['kanban'] = $lang->custom->kanban;
$lang->custom->object['story'] = 'Story';
$lang->custom->object['task'] = 'Tâche';
$lang->custom->object['bug'] = 'Bug';
$lang->custom->object['testcase'] = 'CasTest';
$lang->custom->object['testtask'] = 'Build';
$lang->custom->object['todo'] = 'Agenda';
$lang->custom->object['user'] = 'Utilisateur';
$lang->custom->object['block'] = 'Bloc';
$lang->custom->object['flow'] = 'Flow';
$lang->custom->object['score'] = 'Score';
$lang->custom->object['mode'] = 'Mode';
$lang->custom->object['project'] = 'Project';
$lang->custom->object['product'] = $lang->productCommon;
$lang->custom->object['execution'] = $lang->custom->execution;
$lang->custom->object['kanban'] = $lang->custom->kanban;
$lang->custom->object['story'] = 'Story';
$lang->custom->object['task'] = 'Tâche';
$lang->custom->object['bug'] = 'Bug';
$lang->custom->object['testcase'] = 'CasTest';
$lang->custom->object['testtask'] = 'Build';
$lang->custom->object['todo'] = 'Agenda';
$lang->custom->object['user'] = 'Utilisateur';
$lang->custom->object['block'] = 'Bloc';
$lang->custom->object['flow'] = 'Flow';
$lang->custom->object['score'] = 'Score';
$lang->custom->object['mode'] = 'Mode';
$lang->custom->object['productplan'] = 'Plan';
$lang->custom->object['release'] = 'Release';
$lang->custom->object['testsuite'] = 'Test Suite';
$lang->custom->object['testreport'] = 'Test Report';
$lang->custom->object['caselib'] = 'Case Library';
$lang->custom->menuOrder[5] = 'project';
$lang->custom->menuOrder[10] = 'product';
@@ -129,9 +134,16 @@ $lang->custom->block->fields['closed'] = 'Bloc Fermé';
$lang->custom->project = new stdClass();
$lang->custom->project->currencySetting = 'Currency Setting';
$lang->custom->project->defaultCurrency = 'Default Currency';
$lang->custom->project->fields['required'] = $lang->custom->required;
$lang->custom->project->fields['unitList'] = 'Unit List';
$lang->custom->product = new stdClass();
$lang->custom->product->fields['required'] = $lang->custom->required;
$lang->custom->product->fields['browsestoryconcept'] = 'Story Concpet';
$lang->custom->product->fields['product'] = 'Close Setting';
$lang->custom->story = new stdClass();
$lang->custom->story->fields['required'] = $lang->custom->required;
$lang->custom->story->fields['categoryList'] = 'Category';
$lang->custom->story->fields['priList'] = 'Priorité';
$lang->custom->story->fields['sourceList'] = 'Source';
@@ -143,13 +155,14 @@ $lang->custom->story->fields['reviewResultList'] = 'Valider Résultats';
$lang->custom->story->fields['review'] = 'Validation Requise';
$lang->custom->task = new stdClass();
$lang->custom->task->fields['required'] = $lang->custom->required;
$lang->custom->task->fields['priList'] = 'Priorité';
$lang->custom->task->fields['typeList'] = 'Type';
$lang->custom->task->fields['reasonList'] = 'Raison Fermeture';
$lang->custom->task->fields['statusList'] = 'Statut';
$lang->custom->task->fields['hours'] = 'Effort';
$lang->custom->bug = new stdClass();
$lang->custom->bug->fields['required'] = $lang->custom->required;
$lang->custom->bug->fields['priList'] = 'Priorité';
$lang->custom->bug->fields['severityList'] = 'Sévérité';
$lang->custom->bug->fields['osList'] = 'OS';
@@ -160,6 +173,7 @@ $lang->custom->bug->fields['statusList'] = 'Statut';
$lang->custom->bug->fields['longlife'] = 'Jours Calage';
$lang->custom->testcase = new stdClass();
$lang->custom->testcase->fields['required'] = $lang->custom->required;
$lang->custom->testcase->fields['priList'] = 'Priorité';
$lang->custom->testcase->fields['typeList'] = 'Type';
$lang->custom->testcase->fields['stageList'] = 'Phase';
@@ -168,10 +182,17 @@ $lang->custom->testcase->fields['statusList'] = 'Statut';
$lang->custom->testcase->fields['review'] = 'Validation Requise';
$lang->custom->testtask = new stdClass();
$lang->custom->testtask->fields['required'] = $lang->custom->required;
$lang->custom->testtask->fields['statusList'] = 'Statut';
$lang->custom->testtask->fields['typeList'] = 'Type de test';
$lang->custom->testtask->fields['priList'] = 'Priorité';
$lang->custom->testreport = new stdClass();
$lang->custom->testreport->fields['required'] = $lang->custom->required;
$lang->custom->caselib = new stdClass();
$lang->custom->caselib->fields['required'] = $lang->custom->required;
$lang->custom->todo = new stdClass();
$lang->custom->todo->fields['priList'] = 'Priorité';
$lang->custom->todo->fields['typeList'] = 'Type';
+38 -17
View File
@@ -22,7 +22,7 @@ $lang->custom->score = '积分';
$lang->custom->timezone = '时区';
$lang->custom->scoreReset = '重置积分';
$lang->custom->scoreTitle = '积分功能';
$lang->custom->product = $lang->productCommon;
$lang->custom->productName = $lang->productCommon;
$lang->custom->convertFactor = '换算系数';
$lang->custom->region = '区间';
$lang->custom->tips = '提示语';
@@ -89,21 +89,26 @@ $lang->custom->closedExecution = '已关闭' . $lang->custom->execution;
$lang->custom->closedKanban = '已关闭' . $lang->custom->kanban;
$lang->custom->closedProduct = '已关闭' . $lang->productCommon;
$lang->custom->object['project'] = '项目';
$lang->custom->object['product'] = $lang->productCommon;
$lang->custom->object['execution'] = $lang->custom->execution;
$lang->custom->object['kanban'] = $lang->custom->kanban;
$lang->custom->object['story'] = $lang->SRCommon;
$lang->custom->object['task'] = '任务';
$lang->custom->object['bug'] = 'Bug';
$lang->custom->object['testcase'] = '用例';
$lang->custom->object['testtask'] = '测试单';
$lang->custom->object['todo'] = '待办';
$lang->custom->object['user'] = '用户';
$lang->custom->object['block'] = '区块';
$lang->custom->object['flow'] = '流程';
$lang->custom->object['score'] = '积分';
$lang->custom->object['mode'] = '模式';
$lang->custom->object['project'] = '项目';
$lang->custom->object['product'] = $lang->productCommon;
$lang->custom->object['execution'] = $lang->custom->execution;
$lang->custom->object['kanban'] = $lang->custom->kanban;
$lang->custom->object['story'] = $lang->SRCommon;
$lang->custom->object['task'] = '任务';
$lang->custom->object['bug'] = 'Bug';
$lang->custom->object['testcase'] = '用例';
$lang->custom->object['testtask'] = '测试单';
$lang->custom->object['todo'] = '待办';
$lang->custom->object['user'] = '用户';
$lang->custom->object['block'] = '区块';
$lang->custom->object['flow'] = '流程';
$lang->custom->object['score'] = '积分';
$lang->custom->object['mode'] = '模式';
$lang->custom->object['productplan'] = '计划';
$lang->custom->object['release'] = '发布';
$lang->custom->object['testsuite'] = '套件';
$lang->custom->object['testreport'] = '测试报告';
$lang->custom->object['caselib'] = '用例库';
$lang->custom->menuOrder[5] = 'project';
$lang->custom->menuOrder[10] = 'product';
@@ -129,9 +134,16 @@ $lang->custom->block->fields['closed'] = '关闭的区块';
$lang->custom->project = new stdClass();
$lang->custom->project->currencySetting = '货币设置';
$lang->custom->project->defaultCurrency = '默认货币';
$lang->custom->project->fields['required'] = $lang->custom->required;
$lang->custom->project->fields['unitList'] = '预算单位';
$lang->custom->product = new stdClass();
$lang->custom->product->fields['required'] = $lang->custom->required;
$lang->custom->product->fields['browsestoryconcept'] = '需求概念';
$lang->custom->product->fields['product'] = '关闭设置';
$lang->custom->story = new stdClass();
$lang->custom->story->fields['required'] = $lang->custom->required;
$lang->custom->story->fields['categoryList'] = '类型';
$lang->custom->story->fields['priList'] = '优先级';
$lang->custom->story->fields['sourceList'] = '来源';
@@ -143,13 +155,14 @@ $lang->custom->story->fields['reviewResultList'] = '评审结果';
$lang->custom->story->fields['review'] = '评审流程';
$lang->custom->task = new stdClass();
$lang->custom->task->fields['required'] = $lang->custom->required;
$lang->custom->task->fields['priList'] = '优先级';
$lang->custom->task->fields['typeList'] = '类型';
$lang->custom->task->fields['reasonList'] = '关闭原因';
$lang->custom->task->fields['statusList'] = '状态';
$lang->custom->task->fields['hours'] = '工时';
$lang->custom->bug = new stdClass();
$lang->custom->bug->fields['required'] = $lang->custom->required;
$lang->custom->bug->fields['priList'] = '优先级';
$lang->custom->bug->fields['severityList'] = '严重程度';
$lang->custom->bug->fields['osList'] = '操作系统';
@@ -160,6 +173,7 @@ $lang->custom->bug->fields['statusList'] = '状态';
$lang->custom->bug->fields['longlife'] = '久未处理天数';
$lang->custom->testcase = new stdClass();
$lang->custom->testcase->fields['required'] = $lang->custom->required;
$lang->custom->testcase->fields['priList'] = '优先级';
$lang->custom->testcase->fields['typeList'] = '类型';
$lang->custom->testcase->fields['stageList'] = '阶段';
@@ -168,10 +182,17 @@ $lang->custom->testcase->fields['statusList'] = '状态';
$lang->custom->testcase->fields['review'] = '评审流程';
$lang->custom->testtask = new stdClass();
$lang->custom->testtask->fields['required'] = $lang->custom->required;
$lang->custom->testtask->fields['statusList'] = '状态';
$lang->custom->testtask->fields['typeList'] = '测试类型';
$lang->custom->testtask->fields['priList'] = '优先级';
$lang->custom->testreport = new stdClass();
$lang->custom->testreport->fields['required'] = $lang->custom->required;
$lang->custom->caselib = new stdClass();
$lang->custom->caselib->fields['required'] = $lang->custom->required;
$lang->custom->todo = new stdClass();
$lang->custom->todo->fields['priList'] = '优先级';
$lang->custom->todo->fields['typeList'] = '类型';
+42 -41
View File
@@ -9,49 +9,50 @@
* @version $Id: browsestoryconcept.html.php 4129 2020-09-01 01:58:14Z sgm $
*/
?>
<?php include '../../common/view/header.html.php';?>
<style>
.table-form>tbody>tr>th{text-align: center}
</style>
<div id='mainMenu' class='clearfix'>
<div class='pull-right'>
<?php if(common::hasPriv('custom', 'setstoryconcept')) echo html::a($this->createLink('custom', 'setstoryconcept', '', '', true), $lang->custom->setStoryConcept, '', "class='btn btn-primary iframe' data-width=" . ($this->config->URAndSR ? "590px" : "405px"));?>
</div>
</div>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<div id='mainContent' class='main-row'>
<?php include 'sidebar.html.php';?>
<div class='main-col main-content main-table'>
<table class='table table-form'>
<thead>
<tr>
<?php if(common::hasPriv('custom', 'setDefaultConcept')):?>
<th class='c-default text-center'><?php echo $lang->custom->default;?> </th>
<?php endif;?>
<?php if($this->config->URAndSR):?>
<th class='text-left'><?php echo $lang->custom->URConcept;?> </th>
<?php endif;?>
<th class='text-left'><?php echo $lang->custom->SRConcept;?> </th>
<th class='c-actions-2 text-left'><?php echo $lang->actions;?> </th>
</tr>
</thead>
<tbody>
<?php foreach($URSRList as $key => $URSR):?>
<tr>
<?php if(common::hasPriv('custom', 'setDefaultConcept')):?>
<td class='text-center'><input type="radio" name='default' value='<?php echo $key;?>' <?php if($key == $config->custom->URSR) echo 'checked';?>></td>
<?php endif;?>
<?php if($this->config->URAndSR):?>
<td class='text-left URBox'><?php echo $URSR['URName'];?></td>
<?php endif;?>
<td class='text-left SRBox'><?php echo $URSR['SRName'];?></td>
<td class='c-actions'>
<?php $disabled = $key == $config->custom->URSR ? "disabled=disabled" : '';?>
<?php if(common::hasPriv('custom', 'editStoryConcept')) echo html::a($this->createLink('custom', 'editStoryConcept', "id=$key", '', true), "<i class='icon icon-edit'></i>", '', "class='btn iframe' data-width=" . ($this->config->URAndSR ? "480px" : "330px") . " title={$lang->edit}");?>
<?php if(common::hasPriv('custom', 'deleteStoryConcept')) echo html::a($this->createLink('custom', 'deleteStoryConcept', "id=$key"), "<i class='icon icon-trash'></i>", 'hiddenwin', "class='btn' $disabled title={$lang->delete} data-group='admin'");?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div>
<div class='pull-left'>
<strong><?php echo $lang->custom->product->fields['browsestoryconcept']?></strong>
</div>
<div class='pull-right setBtn'>
<?php if(common::hasPriv('custom', 'setstoryconcept')) echo html::a($this->createLink('custom', 'setstoryconcept', '', '', true), $lang->custom->setStoryConcept, '', "class='btn btn-primary iframe' data-width=" . ($this->config->URAndSR ? "590px" : "405px"));?>
</div>
</div>
<table class='table table-form'>
<thead>
<tr>
<?php if(common::hasPriv('custom', 'setDefaultConcept')):?>
<th class='c-default text-center'><?php echo $lang->custom->default;?> </th>
<?php endif;?>
<?php if($this->config->URAndSR):?>
<th class='text-left'><?php echo $lang->custom->URConcept;?> </th>
<?php endif;?>
<th class='text-left'><?php echo $lang->custom->SRConcept;?> </th>
<th class='c-actions-2 text-left'><?php echo $lang->actions;?> </th>
</tr>
</thead>
<tbody>
<?php foreach($URSRList as $key => $URSR):?>
<tr>
<?php if(common::hasPriv('custom', 'setDefaultConcept')):?>
<td class='text-center'><input type="radio" name='default' value='<?php echo $key;?>' <?php if($key == $config->custom->URSR) echo 'checked';?>></td>
<?php endif;?>
<?php if($this->config->URAndSR):?>
<td class='text-left URBox'><?php echo $URSR['URName'];?></td>
<?php endif;?>
<td class='text-left SRBox'><?php echo $URSR['SRName'];?></td>
<td class='c-actions'>
<?php $disabled = $key == $config->custom->URSR ? "disabled=disabled" : '';?>
<?php if(common::hasPriv('custom', 'editStoryConcept')) echo html::a($this->createLink('custom', 'editStoryConcept', "id=$key", '', true), "<i class='icon icon-edit'></i>", '', "class='btn iframe' data-width=" . ($this->config->URAndSR ? "480px" : "330px") . " title={$lang->edit}");?>
<?php if(common::hasPriv('custom', 'deleteStoryConcept')) echo html::a($this->createLink('custom', 'deleteStoryConcept', "id=$key"), "<i class='icon icon-trash'></i>", 'hiddenwin', "class='btn' $disabled title={$lang->delete} data-group='admin'");?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</div>
</div>
<script>
+1 -1
View File
@@ -9,7 +9,7 @@
* @link http://www.zentao.net
*/
?>
<?php include 'header.html.php';?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<div id='mainContent' class='main-content'>
<form class="load-indicator main-form form-ajax" method='post'>
<table class='table table-form'>
+1 -1
View File
@@ -9,7 +9,7 @@
* @version $Id: deny.html.php 4129 2013-01-18 01:58:14Z wwccss $
*/
?>
<?php include 'header.html.php';?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<?php if(isset($this->config->conceptSetted)):?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
-24
View File
@@ -1,24 +0,0 @@
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
<?php
$menuOrder = $lang->custom->menuOrder;
ksort($menuOrder);
foreach($menuOrder as $order => $object)
{
$name = $lang->custom->object[$object];
if(strpos($lang->custom->dividerMenu, $object) !== false) echo "<span class='divider'></span>";
if(strpos($lang->custom->separatePage, $object))
{
common::printLink('custom', $object, "", "<span class='text'>{$lang->custom->$object}</span>", '', "class='btn btn-link' id='{$object}Tab'");
}
else
{
common::printLink('custom', 'set', "module=$object&field=" . key($lang->custom->{$object}->fields), "<span class='text'>{$name}</span>", '', "class='btn btn-link' id='{$object}Tab'");
}
if($object == 'user') common::printLink('custom', 'required', "", "<span class='text'>{$lang->custom->required}</span>", '', "class='btn btn-link' id='requiredTab'");
}
?>
</div>
</div>
+1 -1
View File
@@ -9,7 +9,7 @@
* @link http://www.zentao.net
*/
?>
<?php include 'header.html.php';?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<div id='mainContent' class='main-content'>
<form class="load-indicator main-form form-ajax" method='post'>
<table class='table table-form'>
+31 -28
View File
@@ -9,34 +9,37 @@
* @link http://www.zentao.net
*/
?>
<?php include 'header.html.php';?>
<div id='mainContent' class='main-content'>
<form class="load-indicator main-form form-ajax" method='post'>
<table class='table table-form'>
<tr>
<th class='w-150px'><?php echo $lang->custom->closedProduct;?></th>
<td class='w-300px text-left'>
<?php $checkedKey = isset($config->CRProduct) ? $config->CRProduct : 0;?>
<?php foreach($lang->custom->CRProduct as $key => $value):?>
<label class="radio-inline"><input type="radio" name="product" value="<?php echo $key?>"<?php echo $key == $checkedKey ? " checked='checked'" : ''?> id="product<?php echo $key;?>"><?php echo $value;?></label>
<?php endforeach;?>
</td>
<td></td>
</tr>
<tr>
<th></th>
<td colspan="2" id="readOnlyOfProduct">
<i class="icon-exclamation-sign"></i>&nbsp;<?php echo $lang->custom->notice->readOnlyOfProduct;?>
</td>
</tr>
<tr>
<th></th>
<td class='form-actions'>
<?php echo html::submitButton();?>
</td>
</tr>
</table>
</form>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<div id='mainContent' class='main-row'>
<?php include 'sidebar.html.php';?>
<div class='main-col main-content'>
<form class="load-indicator main-form form-ajax" method='post'>
<table class='table table-form'>
<tr>
<th class='w-150px'><?php echo $lang->custom->closedProduct;?></th>
<td class='w-300px text-left'>
<?php $checkedKey = isset($config->CRProduct) ? $config->CRProduct : 0;?>
<?php foreach($lang->custom->CRProduct as $key => $value):?>
<label class="radio-inline"><input type="radio" name="product" value="<?php echo $key?>"<?php echo $key == $checkedKey ? " checked='checked'" : ''?> id="product<?php echo $key;?>"><?php echo $value;?></label>
<?php endforeach;?>
</td>
<td></td>
</tr>
<tr>
<th></th>
<td colspan="2" id="readOnlyOfProduct">
<i class="icon-exclamation-sign"></i>&nbsp;<?php echo $lang->custom->notice->readOnlyOfProduct;?>
</td>
</tr>
<tr>
<th></th>
<td class='form-actions'>
<?php echo html::submitButton();?>
</td>
</tr>
</table>
</form>
</div>
</div>
<script>
$(function()
+9 -37
View File
@@ -10,35 +10,14 @@
* @link http://www.zentao.net
*/
?>
<?php include 'header.html.php';?>
<script>
$('#navbar ul.nav li').removeClass('active');
$('#navbar ul.nav li[data-id=<?php echo $moduleName?>]').addClass('active');
<?php if($moduleName == 'bug'):?>
$('#navbar ul.nav li[data-id=qa]').addClass('active');
<?php endif;?>
if($('#navbar ul.nav li[data-id=common]').length > 0) $('#navbar ul.nav li[data-id=common]').addClass('active');
</script>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<div id='mainContent' class='main-row'>
<div class='side-col' id='sidebar'>
<div class='cell'>
<div class='list-group'>
<?php
ksort($config->custom->requiredModules);
foreach($config->custom->requiredModules as $requiredModule)
{
$requiredModuleName = zget($lang->custom->moduleName, $requiredModule, $lang->$requiredModule->common);
echo html::a(inlink('required', "module=$requiredModule"), $requiredModuleName, '', "id='{$requiredModule}Tab'");
}
?>
</div>
</div>
</div>
<?php if(!in_array($module, array('productplan', 'release', 'testsuite', 'testreport', 'caselib')) and ($module != 'project' or ($module == 'project' and $config->vision == 'rnd'))) include 'sidebar.html.php';?>
<div class='main-col main-content'>
<form class="load-indicator main-form form-ajax" method='post'>
<div class='main-header'>
<div class='heading'>
<strong><?php echo $lang->$moduleName->common?></strong>
<strong><?php echo $lang->custom->object[$module] . $lang->arrow . $lang->custom->required;?></strong>
</div>
</div>
<table class='table table-form mw-800px'>
@@ -47,18 +26,18 @@ if($('#navbar ul.nav li[data-id=common]').length > 0) $('#navbar ul.nav li[data-
<tr>
<th class='thWidth'>
<?php
$fields = $this->custom->getFormFields($moduleName, $method);
$fields = $this->custom->getFormFields($module, $method);
if(empty($fields)) continue;
if($moduleName == 'caselib' and $method == 'createcase') continue;
if($module == 'caselib' and $method == 'createcase') continue;
$actionKey = $method . 'Action';
if(isset($lang->$moduleName->$actionKey))
if(isset($lang->$module->$actionKey))
{
echo $lang->$moduleName->$actionKey . $lang->custom->page;
echo $lang->$module->$actionKey . $lang->custom->page;
}
else
{
echo $lang->$moduleName->$method . $lang->custom->page;
echo $lang->$module->$method . $lang->custom->page;
}
?>
</th>
@@ -71,18 +50,11 @@ if($('#navbar ul.nav li[data-id=common]').length > 0) $('#navbar ul.nav li[data-
<th></th>
<td colspan='2' class='form-actions'>
<?php echo html::submitButton();?>
<?php if(common::hasPriv('custom', 'resetRequired')) echo html::a(inlink('resetRequired', "module=$moduleName"), $lang->custom->restore, 'hiddenwin', "class='btn btn-wide'");?>
<?php if(common::hasPriv('custom', 'resetRequired')) echo html::a(inlink('resetRequired', "module=$module"), $lang->custom->restore, 'hiddenwin', "class='btn btn-wide'");?>
</td>
</tr>
</table>
</form>
</div>
</div>
<script>
$(function()
{
$('#mainMenu #requiredTab').addClass('btn-active-text');
$('#sidebar #<?php echo $moduleName?>Tab').addClass('active');
})
</script>
<?php include '../../common/view/footer.html.php';?>
+1 -1
View File
@@ -9,7 +9,7 @@
* @link http://www.zentao.net
*/
?>
<?php include 'header.html.php';?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<div id='mainContent' class='main-content'>
<form class="load-indicator main-form form-ajax" method='post'>
<div class='main-header'>
+2 -23
View File
@@ -10,7 +10,7 @@
* @link http://www.zentao.net
*/
?>
<?php include 'header.html.php';?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<?php
$itemRow = <<<EOT
<tr class='text-center'>
@@ -36,16 +36,6 @@ EOT;
<?php js::set('field', $field)?>
<?php js::set('confirmReviewCase', $lang->custom->notice->confirmReviewCase)?>
<?php js::set('stopSubmit', true)?>
<script>
$('#navbar ul.nav li').removeClass('active');
$('#navbar ul.nav li[data-id=<?php echo $module?>]').addClass('active');
<?php if($module == 'todo'):?>
$('#navbar ul.nav li[data-id=my]').addClass('active');
<?php endif;?>
<?php if($module == 'baseline'):?>
$('#navbar ul.nav li[data-id=type]').addClass('active');
<?php endif;?>
</script>
<?php if($module == 'story' and $field == 'review'):?>
<style>
.table-form>tbody>tr>th {width: 120px !important}
@@ -58,18 +48,7 @@ $('#navbar ul.nav li[data-id=type]').addClass('active');
</style>
<?php endif;?>
<div id='mainContent' class='main-row'>
<div class='side-col' id='sidebar'>
<div class='cell'>
<div class='list-group'>
<?php
foreach($lang->custom->{$module}->fields as $key => $value)
{
echo html::a(inlink('set', "module=$module&field=$key"), $value, '', " id='{$key}Tab'");
}
?>
</div>
</div>
</div>
<?php if(!in_array($module, array('block'))) include 'sidebar.html.php';?>
<div class='main-col main-content'>
<form class="load-indicator main-form form-ajax" method='post'>
<div class='main-header'>
+22
View File
@@ -0,0 +1,22 @@
<div class='side-col' id='sidebar'>
<div class='cell'>
<div class='list-group tab-menu'>
<?php
foreach($lang->custom->{$module}->fields as $key => $value)
{
$params = $key == 'required' ? "module=$module" : '';
$method = $key;
$active = $app->rawMethod == $key ? 'active' : '';
if(!in_array($key, $config->custom->notSetMethods))
{
$params = "module=$module&field=$key";
$method = 'set';
$active = (isset($field) and $field == $key) ? 'active' : $active;
}
if(common::hasPriv('custom', $method)) echo html::a(inlink($method, $params), $value, '', "class='$active'");
}
?>
</div>
</div>
</div>
-35
View File
@@ -1,35 +0,0 @@
<?php
/**
* The set view file of custom module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Tingting Dai <daitingting@xirangit.com>
* @package custom
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include 'header.html.php';?>
<div id='mainContent' class='main-content'>
<form class="load-indicator main-form form-ajax" method='post'>
<div class='main-header'>
<div class='heading'>
<strong><?php echo $lang->custom->working?></strong>
</div>
</div>
<table class='table table-form'>
<tr>
<th class='text-top'><?php echo $lang->custom->working;?></th>
<td>
<?php $checkedKey = isset($config->global->flow) ? $config->global->flow : 'full';?>
<?php foreach($lang->custom->workingList as $key => $value):?>
<p><label class="radio-inline"><input type="radio" name="flow" value="<?php echo $key?>"<?php echo $key == $checkedKey ? " checked='checked'" : ''?> id="flow<?php echo $key;?>"><?php echo $value;?></label></p>
<?php endforeach;?>
</td>
</tr>
<tr><td></td><td><?php echo html::submitButton()?></td></tr>
</table>
</form>
</div>
<?php include '../../common/view/footer.html.php';?>
+26 -13
View File
@@ -75,6 +75,7 @@ $lang->moduleOrder[225] = 'mr';
$lang->moduleOrder[230] = 'app';
$lang->moduleOrder[235] = 'gogs';
$lang->moduleOrder[240] = 'gitea';
$lang->moduleOrder[245] = 'holiday';
$lang->resource = new stdclass();
@@ -1239,18 +1240,23 @@ $lang->zahost->methodOrder[30] = 'downloadImage';
$lang->zahost->methodOrder[35] = 'cancelDownload';
$lang->resource->zanode = new stdclass();
$lang->resource->zanode->browse = 'browse';
$lang->resource->zanode->create = 'create';
$lang->resource->zanode->edit = 'edit';
$lang->resource->zanode->destroy = 'destroy';
$lang->resource->zanode->reboot = 'reboot';
$lang->resource->zanode->suspend = 'suspend';
$lang->resource->zanode->resume = 'resume';
$lang->resource->zanode->getVNC = 'getVNC';
$lang->resource->zanode->start = 'boot';
$lang->resource->zanode->close = 'shutdown';
$lang->resource->zanode->view = 'view';
$lang->resource->zanode->createImage = 'createImage';
$lang->resource->zanode->browse = 'browse';
$lang->resource->zanode->create = 'create';
$lang->resource->zanode->edit = 'edit';
$lang->resource->zanode->destroy = 'destroy';
$lang->resource->zanode->reboot = 'reboot';
$lang->resource->zanode->suspend = 'suspend';
$lang->resource->zanode->resume = 'resume';
$lang->resource->zanode->getVNC = 'getVNC';
$lang->resource->zanode->start = 'boot';
$lang->resource->zanode->close = 'shutdown';
$lang->resource->zanode->view = 'view';
$lang->resource->zanode->createImage = 'createImage';
$lang->resource->zanode->browseSnapshot = 'browseSnapshot';
$lang->resource->zanode->createSnapshot = 'createSnapshot';
$lang->resource->zanode->editSnapshot = 'editSnapshot';
$lang->resource->zanode->restoreSnapshot = 'restoreSnapshot';
$lang->resource->zanode->deleteSnapshot = 'deleteSnapshot';
$lang->zanode->methodOrder[0] = 'browse';
$lang->zanode->methodOrder[5] = 'create';
@@ -1264,6 +1270,11 @@ $lang->zanode->methodOrder[40] = 'start';
$lang->zanode->methodOrder[45] = 'close';
$lang->zanode->methodOrder[50] = 'view';
$lang->zanode->methodOrder[55] = 'createImage';
$lang->zanode->methodOrder[60] = 'browseSnapshot';
$lang->zanode->methodOrder[65] = 'createSnapshot';
$lang->zanode->methodOrder[70] = 'editSnapshot';
$lang->zanode->methodOrder[75] = 'restoreSnapshot';
$lang->zanode->methodOrder[80] = 'deleteSnapshot';
$lang->resource->repo = new stdclass();
$lang->resource->repo->browse = 'browseAction';
@@ -1413,7 +1424,7 @@ $lang->mail->methodOrder[50] = 'resend';
$lang->resource->custom = new stdclass();
$lang->resource->custom->index = 'index';
$lang->resource->custom->set = 'set';
$lang->resource->custom->product = 'product';
$lang->resource->custom->product = 'productName';
$lang->resource->custom->execution = 'execution';
$lang->resource->custom->required = 'required';
$lang->resource->custom->restore = 'restore';
@@ -1921,11 +1932,13 @@ $lang->resource->holiday->create = 'createAction';
$lang->resource->holiday->edit = 'editAction';
$lang->resource->holiday->delete = 'deleteAction';
$lang->resource->holiday->browse = 'browse';
$lang->resource->holiday->import = 'importAction';
$lang->holiday->methodOrder[0] = 'browse';
$lang->holiday->methodOrder[5] = 'create';
$lang->holiday->methodOrder[10] = 'edit';
$lang->holiday->methodOrder[15] = 'delete';
$lang->holiday->methodOrder[20] = 'import';
/* Action. */
$lang->resource->action = new stdclass();
+2
View File
@@ -3,3 +3,5 @@ if(!isset($config->holiday)) $config->holiday = new stdclass();
$config->holiday->require = new stdclass();
$config->holiday->require->create = 'name,begin,end';
$config->holiday->require->edit = 'name,begin,end';
$config->holiday->apiRoot = 'https://ghproxy.com/https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/%d.json';
+33
View File
@@ -31,9 +31,18 @@ class holiday extends control
*/
public function browse($year = '')
{
if(empty($year)) $year = date('Y');
$holidays = $this->holiday->getList($year);
$yearList = $this->holiday->getYearPairs();
$yearAndNext = array(date('Y'), date('Y') + 1);
foreach($yearAndNext as $date)
{
if(!in_array($date, $yearList)) $yearList[$date] = $date;
}
krsort($yearList);
$this->view->title = $this->lang->holiday->browse;
$this->view->holidays = $holidays;
$this->view->yearList = $yearList;
@@ -114,4 +123,28 @@ class holiday extends control
return print(js::reload('parent'));
}
}
/**
* Import holiday.
*
* @param string $year
* @access public
* @return void
*/
public function import($year = '')
{
if(empty($year)) $year = date('Y');
$holidays = $this->holiday->getHolidayByAPI($year);
if(helper::isAjaxRequest())
{
$this->holiday->batchCreate($holidays);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->holidays = $holidays;
$this->display();
}
}
+3
View File
@@ -3,3 +3,6 @@
.with-side .main {padding-left: 145px; float: left;}
.side-col {width: 160px;}
.panel-sm .panel-body {padding: 10px;}
#mainMenu .input-control {display: flex; width: 200px;}
#mainMenu .input-control .form-name {margin: 8px 10px; white-space: pre;}
.table-import {padding-top: 6px;}
+7
View File
@@ -0,0 +1,7 @@
$(function()
{
$(document).on('change', '#year', function()
{
window.location.href = createLink('holiday', 'browse', 'year=' + $(this).val()) + '?_single=1';
});
});
+4 -1
View File
@@ -9,6 +9,7 @@ $lang->holiday->delete = 'Delete';
$lang->holiday->createAction = 'Create Holiday';
$lang->holiday->editAction = 'Edit Holiday';
$lang->holiday->deleteAction = 'Delete Holiday';
$lang->holiday->importAction = 'Import Holiday';
$lang->holiday->id = 'ID';
$lang->holiday->name = 'Name';
@@ -18,10 +19,12 @@ $lang->holiday->begin = 'Begin';
$lang->holiday->end = 'End';
$lang->holiday->all = 'All';
$lang->holiday->holiday = 'Holiday';
$lang->holiday->holiday = 'Holiday';
$lang->holiday->checkYear = 'Year selection';
$lang->holiday->typeList['holiday'] = 'Holiday';
$lang->holiday->typeList['working'] = 'Working Day';
$lang->holiday->emptyTip = 'No Holiday';
$lang->holiday->confirmDelete = 'Confirm removal of holidays?';
$lang->holiday->importTip = '';
+4 -1
View File
@@ -9,6 +9,7 @@ $lang->holiday->delete = 'Delete';
$lang->holiday->createAction = 'Create Holiday';
$lang->holiday->editAction = 'Edit Holiday';
$lang->holiday->deleteAction = 'Delete Holiday';
$lang->holiday->importAction = 'Import Holiday';
$lang->holiday->id = 'ID';
$lang->holiday->name = 'Name';
@@ -18,10 +19,12 @@ $lang->holiday->begin = 'Begin';
$lang->holiday->end = 'End';
$lang->holiday->all = 'All';
$lang->holiday->holiday = 'Holiday';
$lang->holiday->holiday = 'Holiday';
$lang->holiday->checkYear = 'Year selection';
$lang->holiday->typeList['holiday'] = 'Holiday';
$lang->holiday->typeList['working'] = 'Working Day';
$lang->holiday->emptyTip = 'No Holiday';
$lang->holiday->confirmDelete = 'Confirm removal of holidays?';
$lang->holiday->importTip = '';
+4 -1
View File
@@ -9,6 +9,7 @@ $lang->holiday->delete = 'Delete';
$lang->holiday->createAction = 'Create Holiday';
$lang->holiday->editAction = 'Edit Holiday';
$lang->holiday->deleteAction = 'Delete Holiday';
$lang->holiday->importAction = 'Import Holiday';
$lang->holiday->id = 'ID';
$lang->holiday->name = 'Name';
@@ -18,10 +19,12 @@ $lang->holiday->begin = 'Begin';
$lang->holiday->end = 'End';
$lang->holiday->all = 'All';
$lang->holiday->holiday = 'Holiday';
$lang->holiday->holiday = 'Holiday';
$lang->holiday->checkYear = 'Year selection';
$lang->holiday->typeList['holiday'] = 'Holiday';
$lang->holiday->typeList['working'] = 'Working Day';
$lang->holiday->emptyTip = 'No Holiday';
$lang->holiday->confirmDelete = 'Confirm removal of holidays?';
$lang->holiday->importTip = '';
+7 -4
View File
@@ -6,9 +6,10 @@ $lang->holiday->create = '新建';
$lang->holiday->edit = '编辑';
$lang->holiday->delete = '删除';
$lang->holiday->createAction = '创建节假日';
$lang->holiday->editAction = '编辑节假日';
$lang->holiday->deleteAction = '删除节假日';
$lang->holiday->createAction = '创建节假日';
$lang->holiday->editAction = '编辑节假日';
$lang->holiday->deleteAction = '删除节假日';
$lang->holiday->importAction = '导入节假日';
$lang->holiday->id = '编号';
$lang->holiday->name = '名称';
@@ -18,10 +19,12 @@ $lang->holiday->begin = '开始日期';
$lang->holiday->end = '结束日期';
$lang->holiday->all = '所有';
$lang->holiday->holiday = '假期';
$lang->holiday->holiday = '假期';
$lang->holiday->checkYear = '年份选择';
$lang->holiday->typeList['holiday'] = '假期';
$lang->holiday->typeList['working'] = '补班';
$lang->holiday->emptyTip = '暂时没有节假日。';
$lang->holiday->confirmDelete = '确认删除节假日?';
$lang->holiday->importTip = '可以在此 %s国家法定节假日。';
+76
View File
@@ -408,4 +408,80 @@ class holidayModel extends model
$this->dao->update(TABLE_TASK)->set('realDuration')->eq($realDuration)->where('id')->eq($task->id)->exec();
}
}
/**
* Get holidays by api.
*
* @param string $year
* @access public
* @return array
*/
public function getHolidayByAPI($year = '')
{
if(empty($year)) $year = date('Y');
$apiRoot = sprintf($this->config->holiday->apiRoot, $year);
$data = json_decode(common::http($apiRoot));
$days = isset($data->days) ? (array)$data->days : array();
$holidays = array();
$privDay = 0;
$prevDayOff = true;
$daysIndex = count($days) - 1;
foreach($days as $index => $day)
{
if($index < $daysIndex and (strtotime($day->date) - $privDay > 86400 or $day->isOffDay != $prevDayOff))
{
$holiday = new stdClass();
$holiday->type = $day->isOffDay ? 'holiday' : 'working';
$holiday->name = $day->name . zget($this->lang->holiday->typeList, $holiday->type);
$holiday->begin = $day->date;
$holiday->end = '';
$holidays[] = $holiday;
}
if(isset($holiday) or $index == $daysIndex)
{
$holidayNum = count($holidays);
if($holidayNum > 1)
{
if(isset($holiday))
{
$holidays[$holidayNum - 2]->end = date('Y-m-d', $privDay);
}
else
{
$holidays[$holidayNum - 1]->end = $day->date;
}
}
if(isset($holiday)) unset($holiday);
}
$privDay = strtotime($day->date);
$prevDayOff = $day->isOffDay;
}
return $holidays;
}
/**
* Batch create holiday.
*
* @param array $holidays
* @access public
* @return int|bool
*/
public function batchCreate($holidays)
{
foreach($holidays as $holiday)
{
$this->dao->insert(TABLE_HOLIDAY)->data($holiday)
->autoCheck()
->batchCheck($this->config->holiday->require->create, 'notempty')
->check('end', 'ge', $holiday->begin)
->exec();
}
if(dao::isError()) return false;
$lastInsertID = $this->dao->lastInsertID();
return $lastInsertID;
}
}
+19 -24
View File
@@ -13,38 +13,26 @@
<?php include '../../common/view/header.html.php';?>
<div id='mainMenu' class='clearfix'>
<div class='pull-left btn-toolbar'>
<?php
echo html::a($this->createLink('holiday', 'browse'), '<span class="text">' . $lang->holiday->all . '</span>', '', "class='btn btn-link btn-active-text' data-app='oa'");
?>
<div class='input-control'>
<span class="form-name"><strong><?php echo $lang->holiday->checkYear;?></strong></span>
<?php echo html::select('year', $yearList, $currentYear, "class='form-control chosen'");?>
</div>
</div>
<div class='pull-right'>
<?php common::printLink('holiday', 'create', "", "<i class='icon icon-plus'> </i>" . $lang->holiday->create, '', "class='btn btn-primary iframe'", '', true)?>
</div>
</div>
<div id='mainContent' class='main-row fade in'>
<div class='side-col'>
<div class='panel panel-sm'>
<div class='panel-body'>
<ul class='tree' data-ride='tree' data-collapsed='true'>
<?php foreach($yearList as $year):?>
<li class='<?php echo $year == $currentYear ? 'active' : ''?>'>
<?php common::printLink('holiday', 'browse', "year=$year", $year);?>
</li>
<?php endforeach;?>
</ul>
</div>
</div>
</div>
<div class='main-col main-table'>
<?php if(!empty($holidays)):?>
<?php if(!empty($holidays)):?>
<table class='table has-sort-head'>
<thead>
<tr>
<th class='w-150px'><?php echo $lang->holiday->name;?></th>
<th class='w-200px'><?php echo $lang->holiday->holiday;?></th>
<th class='w-80px'><?php echo $lang->holiday->type;?></th>
<th><?php echo $lang->holiday->desc;?></th>
<th class='w-100px'><?php echo $lang->actions;?></th>
<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-actions-2'><?php echo $lang->actions;?></th>
</tr>
</thead>
<?php foreach($holidays as $holiday):?>
@@ -60,13 +48,20 @@
</tr>
<?php endforeach;?>
</table>
<?php else:?>
<?php else:?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->holiday->emptyTip;?></span>
</p>
</div>
<?php endif;?>
<?php endif;?>
<?php if(!common::checkNotCN() and common::hasPriv('holiday', 'import') and $currentYear >= date('Y')):?>
<div class="table-footer">
<div class="table-import">
<?php echo sprintf($lang->holiday->importTip, html::a(helper::createLink('holiday', 'import', "year=$currentYear", '', true), $lang->import, '', "class='text-primary iframe' data-width='400px'"));?>
</div>
</div>
<?php endif;?>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+2 -2
View File
@@ -45,8 +45,8 @@
<th><?php echo $lang->holiday->desc?></th>
<td><?php echo html::textarea('desc', '', "class='form-control'")?></td>
<td></td>
</tr>
<tr><th></th><td clospan='2'><?php echo baseHTML::submitButton();?></td></tr>
</tr>
<tr><th></th><td colspan='2'><?php echo baseHTML::submitButton();?></td></tr>
</table>
</form>
</div>
+2 -2
View File
@@ -45,8 +45,8 @@
<th><?php echo $lang->holiday->desc?></th>
<td><?php echo html::textarea('desc', $holiday->desc, "class='form-control'")?></td>
<td></td>
</tr>
<tr><th></th><td clospan='2'><?php echo baseHTML::submitButton();?></td></tr>
</tr>
<tr><th></th><td colspan='2'><?php echo baseHTML::submitButton();?></td></tr>
</table>
</form>
</div>
+60
View File
@@ -0,0 +1,60 @@
<?php
/**
* The browse view file of holiday module of ZenTao.
*
* @copyright Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author chujilu <chujilu@cnezsoft.com>
* @package holiday
* @version $Id$
* @link https://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<style>
#main > .container {padding: 0;}
.body-modal #mainContent {padding: 0;}
.modal-iframe .modal-header {display: none;}
#mainContent .table {margin-bottom: 0;}
#mainContent .table thead th {padding-top: 20px;}
#mainContent .table tr {height: 40px;}
#mainContent .table .c-name {padding-left: 40px;}
#mainContent .table .c-time-limit {padding-right: 40px;}
.body-modal .table-footer {margin-top: 20px;}
#mainContent .table-footer .btn-cancel {margin-left: 16px;}
</style>
<div id='mainContent' class='main-content'>
<div class='center-block main-table'>
<?php if(!empty($holidays)):?>
<form class='form-ajax' method='post'>
<table class='table table-fixed'>
<thead>
<tr>
<th class="c-name"><?php echo $lang->holiday->name;?></th>
<th class="c-time-limit"><?php echo $lang->holiday->holiday;?></th>
</tr>
</thead>
<tbody>
<?php foreach($holidays as $holiday):?>
<tr>
<td class="c-name"><?php echo $holiday->name;?></td>
<td class="c-time-limit"><?php echo formatTime($holiday->begin, DT_DATE1) . ' ~ ' . formatTime($holiday->end, DT_DATE1);?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class="table-footer text-center">
<?php echo html::submitButton($lang->import, '', 'btn btn-primary');?>
<?php echo html::commonButton($lang->cancel, 'data-dismiss="modal"', 'btn btn-cancel');?>
</div>
</form>
<?php else:?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->holiday->emptyTip;?></span>
</p>
</div>
<?php endif;?>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+17 -6
View File
@@ -740,8 +740,6 @@ class programplanModel extends model
$datas[] = $plan;
}
$project = $this->loadModel('project')->getByID($projectID);
$productList = $this->loadModel('product')->getProductPairsByProject($projectID);
$totalPercent = 0;
$totalDevType = 0;
@@ -949,10 +947,6 @@ class programplanModel extends model
$this->setTreePath($stageID);
if($data->acl != 'open') $this->user->updateUserView($stageID, 'sprint');
$linkProducts = $project->division ? array(0 => $productID) : array_keys($productList);
$this->post->set('products', $linkProducts);
$this->execution->updateProducts($stageID);
/* Record version change information. */
$spec = new stdclass();
$spec->project = $stageID;
@@ -974,6 +968,23 @@ class programplanModel extends model
}
}
$linkProducts = array();
$linkBranches = array();
$productList = $this->loadModel('product')->getProducts($projectID);
if($project->division)
{
$linkProducts = array(0 => $productID);
$linkBranches = array(0 => $productList[$productID]->branches);
}
else
{
$linkProducts = array_keys($productList);
foreach($linkProducts as $index => $productID) $linkBranches[$index] = $productList[$productID]->branches;
}
$this->post->set('products', $linkProducts);
$this->post->set('branch', $linkBranches);
$this->execution->updateProducts($stageID);
/* If child plans has milestone, update parent plan set milestone eq 0 . */
if($parentID and $milestone) $this->dao->update(TABLE_PROJECT)->set('milestone')->eq(0)->where('id')->eq($parentID)->exec();
+13 -7
View File
@@ -2171,7 +2171,8 @@ class project extends control
$this->loadModel('program');
$this->loadModel('execution');
$project = $this->project->getById($projectID);
$project = $this->project->getById($projectID);
$executions = $this->execution->getPairs($projectID);
if(!empty($_POST))
{
@@ -2182,11 +2183,7 @@ class project extends control
}
$oldProducts = $this->product->getProducts($projectID);
if($project->multiple and $project->model != 'waterfall')
{
$executions = $this->dao->select('id')->from(TABLE_EXECUTION)->where('project')->eq($projectID)->fetchPairs('id');
$oldExecutionProducts = $this->dao->select('project,product')->from(TABLE_PROJECTPRODUCT)->where('project')->in($executions)->fetchGroup('project', 'product');
}
if($project->multiple and $project->model != 'waterfall') $oldExecutionProducts = $this->dao->select('project,product')->from(TABLE_PROJECTPRODUCT)->where('project')->in(array_keys($executions))->fetchGroup('project', 'product');
$this->project->updateProducts($projectID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
@@ -2203,6 +2200,15 @@ class project extends control
$diffProducts = array_merge(array_diff($oldProductIDs, $newProductIDs), array_diff($newProductIDs, $oldProductIDs));
if($diffProducts) $this->loadModel('action')->create('project', $projectID, 'Managed', '', !empty($_POST['products']) ? join(',', $_POST['products']) : '');
if(empty($project->division))
{
foreach(array_keys($executions) as $executionID)
{
$this->execution->updateProducts($executionID);
if($diffProducts) $this->loadModel('action')->create('execution', $executionID, 'Managed', '', implode(',', array_keys($newProducts)));
}
}
if($project->multiple and $project->model != 'waterfall')
{
$unlinkedProducts = array_diff($oldProductIDs, $newProductIDs);
@@ -2317,7 +2323,7 @@ class project extends control
$this->view->unmodifiableBranches = $unmodifiableBranches;
$this->view->unmodifiableMainBranches = $unmodifiableMainBranches;
$this->view->branchGroups = $branchGroups;
$this->view->executions = $this->execution->getPairs($projectID);
$this->view->executions = $executions;
$this->view->allBranches = $this->branch->getByProducts(array_keys($allProducts), 'ignoreNormal');
$this->view->allProducts = $allProducts;
+6
View File
@@ -1634,6 +1634,12 @@ class projectModel extends model
if(!dao::isError())
{
$this->updateProducts($projectID, $_POST['products']);
if(empty($oldProject->division))
{
$executions = $this->loadModel('execution')->getPairs($projectID);
foreach(array_keys($executions) as $executionID) $this->execution->updateProducts($executionID);
}
$this->file->updateObjectID($this->post->uid, $projectID, 'project');
$whitelist = explode(',', $project->whitelist);
-1
View File
@@ -9,7 +9,6 @@
* @version $Id: en.php 4129 2013-01-18 01:58:14Z wwccss $
* @link http://www.zentao.net
*/
$lang->release->common = 'Product Release';
$lang->release->create = "Erstellen";
$lang->release->edit = "Bearbeiten";
$lang->release->linkStory = "Story verknüpfen";
-1
View File
@@ -9,7 +9,6 @@
* @version $Id: en.php 4129 2013-01-18 01:58:14Z wwccss $
* @link http://www.zentao.net
*/
$lang->release->common = 'Product Release';
$lang->release->create = "Create Release";
$lang->release->edit = "Edit Release";
$lang->release->linkStory = "Link Story";
-1
View File
@@ -9,7 +9,6 @@
* @version $Id: en.php 4129 2013-01-18 01:58:14Z wwccss $
* @link http://www.zentao.net
*/
$lang->release->common = 'Product Release';
$lang->release->create = "Créer Release";
$lang->release->edit = "Editer Release";
$lang->release->linkStory = "Intégrer Story";
-1
View File
@@ -9,7 +9,6 @@
* @version $Id: zh-cn.php 4129 2013-01-18 01:58:14Z wwccss $
* @link http://www.zentao.net
*/
$lang->release->common = '产品发布';
$lang->release->create = "创建发布";
$lang->release->edit = "编辑发布";
$lang->release->linkStory = "关联{$lang->SRCommon}";
+1 -1
View File
@@ -5511,7 +5511,7 @@ class storyModel extends model
$stories[$id]->title = $story->title;
$stories[$id]->cases = $this->loadModel('testcase')->getStoryCases($id);
$stories[$id]->bugs = $this->loadModel('bug')->getStoryBugs($id);
$stories[$id]->tasks = $this->loadModel('task')->getStoryTasks($id);
$stories[$id]->tasks = $this->loadModel('task')->getStoryTasks($id, 0, $projectID);
if($this->config->edition == 'max')
{
$stories[$id]->designs = $this->dao->select('id, name')->from(TABLE_DESIGN)
+3 -1
View File
@@ -2722,16 +2722,18 @@ class taskModel extends model
*
* @param int $storyID
* @param int $executionID
* @param int $projectID
* @access public
* @return array
*/
public function getStoryTasks($storyID, $executionID = 0)
public function getStoryTasks($storyID, $executionID = 0, $projectID = 0)
{
$tasks = $this->dao->select('id, parent, name, assignedTo, pri, status, estimate, consumed, closedReason, `left`')
->from(TABLE_TASK)
->where('story')->eq((int)$storyID)
->andWhere('deleted')->eq(0)
->beginIF($executionID)->andWhere('execution')->eq($executionID)->fi()
->beginIF($projectID)->andWhere('project')->eq($projectID)->fi()
->fetchAll('id');
$parents = array();
+2
View File
@@ -39,6 +39,8 @@
.title-group.required:after {display: none;}
.title-group.required > .required:after {display: block; right: 29px; top: 5px;}
#titleBox.required:after{display: block; right: 29px; top: 5px;}
#priRequiredBox.required:after{display: block; right: -12px; top: 5px;}
.pri-selector > .btn {padding: 5px 8px !important; width: 100%;}
.pri-selector > .dropdown-menu {padding: 10px;}
.stageBox {padding-left: 15px !important;}
+6
View File
@@ -36,11 +36,17 @@ $(function()
$searchInput.focus();
});
};
$(document).on('change', '#story', function()
{
if($(this).val() === 'showmore') showSearchModal();
});
$(document).on('click', '#priRequiredBox', function()
{
$('#priSelect').removeClass('required');
});
$(document).on('click', '#story_chosen .chosen-results > li.no-results', showSearchModal);
$searchStories.on('hide.zui.modal', function()
+5 -4
View File
@@ -111,7 +111,7 @@ foreach(explode(',', $config->testcase->create->requiredFields) as $field)
<th><?php echo $lang->testcase->title;?></th>
<td colspan='2'>
<div class="input-group title-group">
<div class="input-control has-icon-right">
<div id='titleBox' class="input-control has-icon-right">
<?php echo html::input('title', $caseTitle, "class='form-control'");?>
<div class="colorpicker">
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown"><span class="cp-title"></span><span class="color-bar"></span><i class="ic"></i></button>
@@ -145,11 +145,12 @@ foreach(explode(',', $config->testcase->create->requiredFields) as $field)
<?php echo html::select('pri', (array)$priList, $pri, "class='form-control priBox $hiddenPri'");?>
<?php else: ?>
<?php ksort($priList);?>
<div class="input-group-btn pri-selector priBox <?php echo $hiddenPri;?>" data-type="pri">
<button type="button" class="btn dropdown-toggle br-0" data-toggle="dropdown">
<?php $hasPri = strpos($config->testcase->create->requiredFields, 'pri') !== false ? True : False;?>
<div class="input-group-btn pri-selector <?php echo $hiddenPri;?>" data-type="pri">
<button <?php echo $hasPri ? "id='priRequiredBox'" : '';?> type="button" class="btn dropdown-toggle br-0 <?php echo $hasPri ? 'required' : '';?>" data-toggle="dropdown">
<span class="pri-text"><span class="label-pri label-pri-<?php echo empty($pri) ? '0' : $pri?>" title="<?php echo $pri?>"><?php echo $pri?></span></span> &nbsp;<span class="caret"></span>
</button>
<div class='dropdown-menu pull-right'>
<div class='dropdown-menu pull-right' id="priSelect">
<?php echo html::select('pri', (array)$priList, $pri, "class='form-control' data-provide='labelSelector' data-label-class='label-pri'");?>
</div>
</div>
-1
View File
@@ -9,7 +9,6 @@
* @version $Id: en.php 4676 2013-04-26 06:08:23Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
$lang->todo->common = 'Todo';
$lang->todo->index = "Home";
$lang->todo->create = "Todo hinzufügen";
$lang->todo->createCycle = "Wiederkehrenden Todo hinzufügen";
-1
View File
@@ -9,7 +9,6 @@
* @version $Id: en.php 4676 2013-04-26 06:08:23Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
$lang->todo->common = 'Todo';
$lang->todo->index = "Home";
$lang->todo->create = "Add Todo";
$lang->todo->createCycle = "Add Recurred Todo";
-1
View File
@@ -9,7 +9,6 @@
* @version $Id: en.php 4676 2013-04-26 06:08:23Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
$lang->todo->common = 'Agenda';
$lang->todo->index = "Accueil";
$lang->todo->create = "Ajout Entrée";
$lang->todo->createCycle = "Ajout Tâche récurrente";
-1
View File
@@ -9,7 +9,6 @@
* @version $Id: vi.php 4676 2020-04-06 06:08:23Z quocnho@gmail.com $
* @link http://www.zentao.net
*/
$lang->todo->common = 'Việc làm';
$lang->todo->index = "Home";
$lang->todo->create = "Thêm việc";
$lang->todo->createCycle = "Thêm việc lặp lại";
-1
View File
@@ -9,7 +9,6 @@
* @version $Id: zh-cn.php 5022 2013-07-05 06:50:39Z chencongzhi520@gmail.com $
* @link http://www.zentao.net
*/
$lang->todo->common = '待办';
$lang->todo->index = "待办一览";
$lang->todo->create = "添加待办";
$lang->todo->createCycle = "创建周期待办";
+4
View File
@@ -122,6 +122,10 @@ class webhookModel extends model
{
$text = substr($data->markdown->content, 0, strpos($data->markdown->content, '(http'));
}
elseif(isset($data->text->content))
{
$text = substr($data->text->content, 0, strpos($data->text->content, '(http'));
}
elseif(isset($data->content))
{
$text = $data->content->text;
+8 -3
View File
@@ -43,8 +43,13 @@ class zahost extends control
$this->loadModel('search')->setSearchParams($this->config->zahost->search);
$showFeature = false;
$skipAutomation = !empty($this->config->global->skipAutomation) ? $this->config->global->skipAutomation : '';
if(strpos(",$skipAutomation,", $this->app->user->account) === false) $showFeature = true;
$accounts = !empty($this->config->global->skipAutomation) ? $this->config->global->skipAutomation : '';
if(strpos(",$accounts,", $this->app->user->account) === false)
{
$showFeature = true;
$accounts .= ',' . $this->app->user->account;
$this->loadModel('setting')->setItem('system.common.global.skipAutomation', $accounts);
}
$this->view->title = $this->lang->zahost->common;
$this->view->hostList = $hostList;
@@ -164,7 +169,7 @@ class zahost extends control
}
$this->dao->update(TABLE_ZAHOST)->set('deleted')->eq(1)->where('id')->eq($hostID)->exec();
$this->loadModel('action')->create('zahost', $hostID, 'deleted');
$this->loadModel('action')->create('zahost', $hostID, 'deleted', '', $extra = ACTIONMODEL::CAN_UNDELETED);
/* if ajax request, send result. */
if($this->server->ajax)
+1
View File
@@ -20,3 +20,4 @@
.btn-info {background-color: unset;}
.icon-refresh {font-size: 15px;}
.load-indicator:after {top: 33%;}
.btn.disabled i {color: #fff;}
-1
View File
@@ -76,7 +76,6 @@ function setIframeHeight(iframe)
{
var height = iframeWin.document.documentElement.scrollHeight || iframeWin.document.body.scrollHeight
iframe.height = height+10;
console.log(1111, iframe.height)
}
}
}
+4 -1
View File
@@ -85,7 +85,10 @@ class zahostModel extends model
$this->dao->update(TABLE_ZAHOST)->data($hostInfo)
->batchCheck($this->config->zahost->create->requiredFields, 'notempty')
->batchCheck('diskSize,memory', 'float');
->batchCheck('diskSize,memory', 'float')
->check('name', 'unique', "id != $hostID and type in ('vhost', 'zahost')")
->autoCheck();
if(dao::isError()) return false;
$ping = $this->checkAddress($hostInfo->extranet);
+8 -26
View File
@@ -131,43 +131,25 @@
<div class="detail-title"><?php echo $lang->zahost->desc;?></div>
<div class="detail-content article-content"><?php echo !empty($zahost->desc) ? htmlspecialchars_decode($zahost->desc) : $lang->noData;?></div>
</div>
<?php if(!empty($nodeList)): ?>
</div>
<?php if(commonModel::hasPriv('zanode', 'browse')):?>
<div class="cell">
<div class="detail">
<div class="detail-title"><?php echo $lang->zahost->browseNode;?></div>
<?php if(!empty($nodeList)): ?>
<div class="detail-content article-content">
<?php echo "<iframe width='100%' id='nodesIframe' src='" . $this->createLink('zanode', 'list', "hostID=$zahost->id", '', true) . "' frameborder='no' allowfullscreen='true' mozallowfullscreen='true' webkitallowfullscreen='true' allowtransparency='true' scrolling='auto' onload='setIframeHeight(this)' style='min-height:300px;'></iframe>";?>
<!-- <table class='table has-sort-head table-fixed' id='nodeList'>
<thead>
<tr>
<th class='c-name'><?php common::printOrderLink('name', $orderBy, $vars, $lang->zahost->name);?></th>
<th class='c-cpu'><?php common::printOrderLink('cpuCores', $orderBy, $vars, $lang->zanode->cpuCores);?></th>
<th class='c-number'><?php common::printOrderLink('memory', $orderBy, $vars, $lang->zanode->memory);?></th>
<th class='c-number'><?php common::printOrderLink('diskSize', $orderBy, $vars, $lang->zanode->diskSize);?></th>
<th class='c-os'><?php common::printOrderLink('osName', $orderBy, $vars, $lang->zanode->osName);?></th>
<th class='c-status'><?php common::printOrderLink('status', $orderBy, $vars, $lang->zanode->status);?></th>
</tr>
</thead>
<tbody>
<?php foreach($nodeList as $node):?>
<tr>
<td title="<?php echo $node->name;?>"><?php echo html::a($this->createLink('zanode', 'view', "id=$node->id"), $node->name, '_target', "");?></td>
<td><?php echo zget($config->zanode->os->cpuCores, $node->cpuCores);?></td>
<td><?php echo $node->memory . $this->lang->zahost->unitList['GB'];?></td>
<td><?php echo $node->diskSize . $this->lang->zahost->unitList['GB'];?></td>
<td><?php echo $node->osName;?></td>
<td><?php echo zget($lang->zanode->statusList, $node->status);?></td>
</tr>
<?php endforeach;?>
</tbody>
</table> -->
</div>
<?php else: ?>
<div class="detail-content article-content"><?php echo $lang->noData;?></div>
<?php endif; ?>
</div>
<?php endif; ?>
<?php
$canBeChanged = common::canBeChanged('zahost', $zahost);
if($canBeChanged) $actionFormLink = $this->createLink('action', 'comment', "objectType=zahost&objectID=$zahost->hostID");
?>
</div>
<?php endif; ?>
<?php $this->printExtendFields($zahost, 'div', "position=left&inForm=0&inCell=1");?>
<div class='main-actions'>
<div class="btn-toolbar">
+156 -2
View File
@@ -44,8 +44,13 @@ class zanode extends control
$this->loadModel('search')->setSearchParams($this->config->zanode->search);
$showFeature = false;
$skipAutomation = !empty($this->config->global->skipAutomation) ? $this->config->global->skipAutomation : '';
if(strpos(",$skipAutomation,", $this->app->user->account) === false) $showFeature = true;
$accounts = !empty($this->config->global->skipAutomation) ? $this->config->global->skipAutomation : '';
if(strpos(",$accounts,", $this->app->user->account) === false)
{
$showFeature = true;
$accounts .= ',' . $this->app->user->account;
$this->loadModel('setting')->setItem('system.common.global.skipAutomation', $accounts);
}
$this->view->title = $this->lang->zanode->common;
$this->view->users = $this->loadModel('user')->getPairs('noletter|nodeleted');
@@ -73,6 +78,10 @@ class zanode extends control
*/
public function list($hostID, $orderBy = 'id_desc')
{
if(!commonModel::hasPriv('zanode', 'browse'))
{
$this->loadModel('common')->deny('zanode', 'browse');
}
$this->view->title = $this->lang->zanode->common;
$this->view->nodeList = $this->loadModel("zanode")->getListByHost($hostID, $orderBy);
$this->view->orderBy = $orderBy;
@@ -155,6 +164,7 @@ class zanode extends control
$this->view->token = !empty($vnc->token) ? $vnc->token:'';
$this->view->title = $this->lang->zanode->view;
$this->view->zanode = $node;
$this->view->snapshotList = $this->zanode->getSnapshotList($id);
$this->view->actions = $this->loadModel('action')->getList('zanode', $id);
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->display();
@@ -276,6 +286,90 @@ class zanode extends control
$this->display();
}
/**
* Create snapshot.
*
* @param int $zanodeID
* @access public
* @return void
*/
public function createSnapshot($nodeID = 0)
{
$node = $this->zanode->getNodeByID($nodeID);
if($_POST)
{
$this->zanode->createSnapshot($nodeID);
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
return $this->send($response);
}
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->node = $node;
$this->display();
}
/**
* Edit Snapshot.
*
* @param int $snapshotID
* @access public
* @return void
*/
public function editSnapshot($snapshotID)
{
$snapshot = $this->zanode->getImageByID($snapshotID);
if($_POST)
{
$this->zanode->editSnapshot($snapshotID);
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
return $this->send($response);
}
$this->loadModel('action')->create('zanode', $snapshot->host, 'editSnapshot', '', $snapshot->localName ? $snapshot->localName : $snapshot->name);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->snapshot = $snapshot;
$this->display();
}
/**
* Delete Snapshot.
*
* @param int $snapshotID
* @param string $confirm
* @access public
* @return void
*/
public function deleteSnapshot($snapshotID, $confirm = 'no')
{
if($confirm == 'no')
{
return print(js::confirm($this->lang->zanode->confirmDeleteSnapshot, inlink('deleteSnapshot', "snapshotID={$snapshotID}&confirm=yes")));
}
$result = $this->zanode->deleteSnapshot($snapshotID);
if($result !== true)
{
return print(js::alert($result));
}
else
{
if(isonlybody()) return print(js::alert($this->lang->zanode->actionSuccess) . js::reload('parent.parent'));
return print(js::alert($this->lang->zanode->actionSuccess) . js::locate($this->createLink('zanode', 'browse'), 'parent'));
}
}
/**
* Desctroy node.
*
@@ -324,6 +418,66 @@ class zanode extends control
$this->display();
}
/**
* Browse snapshot.
*
* @param int $nodeID
* @param string $browseType
* @param int $param
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function browseSnapshot($nodeID, $browseType = 'all', $param = 0, $orderBy = 'id', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->app->loadLang('zahost');
$this->app->loadClass('pager', $static = true);
$pager = pager::init($recTotal, $recPerPage, $pageID);
$snapshotList = $this->zanode->getSnapshotList($nodeID, $browseType, $param, $orderBy, $pager);
$this->view->title = $this->lang->zanode->browseSnapshot;
$this->view->nodeID = $nodeID;
$this->view->node = $this->zanode->getNodeByID($nodeID);
$this->view->snapshotList = $snapshotList;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->pager = $pager;
$this->view->param = $param;
$this->view->orderBy = $orderBy;
$this->view->browseType = $browseType;
$this->display();
}
/**
* Restore node.
*
* @param int $nodeID
* @return void
*/
public function restoreSnapshot($nodeID, $snapshotID, $confirm = 'no')
{
if($confirm == 'no')
{
return print(js::confirm($this->lang->zanode->confirmRestore, inlink('restoreSnapshot', "nodeID={$nodeID}&snapshotID={$snapshotID}&confirm=yes")));
}
$this->zanode->restoreSnapshot($nodeID, $snapshotID);
if(dao::isError())
{
return print(js::alert(dao::getError()) . js::reload('parent'));
}
else
{
if(isonlybody()) return print(js::alert($this->lang->zanode->actionSuccess) . js::reload('parent.parent'));
return print(js::alert($this->lang->zanode->actionSuccess) . js::locate($this->createLink('zanode', 'browse'), 'parent'));
}
}
/**
* Ajax get template pairs by api.
*
+6
View File
@@ -0,0 +1,6 @@
#main{min-width: 0!important;padding:0!important;}
body{background-color: #fff!important;}
.c-createdBy {width: 100px;}
.c-datetime {width: 130px;}
.c-status {width: 120px;}
+1
View File
@@ -16,3 +16,4 @@
.checkStatus{color: #313c52;}
.node-not-wrap{white-space: nowrap;}
.btn-info {background-color: unset;}
.btn.disabled i {color: #fff;}
+7
View File
@@ -0,0 +1,7 @@
$(function()
{
var myPager = $('.pager').data('zui.pager');
myPager.options.menuDirection = 'dropdown';
myPager.set();
});
+20
View File
@@ -160,6 +160,14 @@ $('.btn-pwd-copy').live('click', function()
}, 2000)
})
$('#jumpManual').click(function()
{
var encodedHelpPageUrl = encodeURIComponent('https://www.zentao.net/book/zentaopms/974.html?fullScreen=zentao');
var urlForNewTab = window.location.origin + '#app=help&url=' + encodedHelpPageUrl;
window.open(urlForNewTab)
})
$(function(){
checkServiceStatus();
checkInterval = setInterval(() => {
@@ -171,3 +179,15 @@ $(function(){
checkServiceStatus();
}, 2000);
})
/**
* Edit Snapshot.
*
* @param string $link
* @access public
* @return void
*/
function editSnapshot(link)
{
$('#editSnapshot').attr('href', link).click();
}
+17
View File
@@ -79,6 +79,22 @@ $lang->zanode->createImageSuccess = 'Successed, You can use this image to create
$lang->zanode->createImageFail = 'Failed to create';
$lang->zanode->createImageButton = 'Create image';
$lang->zanode->snapshotName = 'Snapshot Name';
$lang->zanode->browseSnapshot = 'Snapshot List';
$lang->zanode->createSnapshot = 'Create Snapshot';
$lang->zanode->editSnapshot = 'Edit Snapshot';
$lang->zanode->restoreSnapshot = 'Revert Snapshot';
$lang->zanode->deleteSnapshot = 'Delete Snapshot';
$lang->zanode->snapshotEmpty = 'No snapshots';
$lang->zanode->confirmDeleteSnapshot = "The snapshot cannot be restored from the recycle bin after being deleted. Are you sure to continue?";
$lang->zanode->snapshot->statusList['creating'] = 'Creating';
$lang->zanode->snapshot->statusList['completed'] = 'Create Completed';
$lang->zanode->snapshot->statusList['failed'] = 'Create Failed';
$lang->zanode->snapshot->statusList['restoring'] = 'Restoring';
$lang->zanode->snapshot->statusList['restore_failed'] = 'Restore Failed';
$lang->zanode->snapshot->statusList['restore_completed'] = 'Restore Completed';
$lang->zanode->imageNameEmpty = 'Name can not be empty.';
$lang->zanode->runTimeout = 'Network connection timeout, please check the host and execution node status.';
@@ -101,6 +117,7 @@ $lang->zanode->statusList['shutodown'] = 'shutdown';
$lang->zanode->statusList['destroy_fail'] = 'Destroy Fail';
$lang->zanode->statusList['wait'] = 'Initializing';
$lang->zanode->statusList['online'] = 'Online';
$lang->zanode->statusList['restoring'] = 'Restoring';
$lang->zanode->initNotice = "Succeeded. Please initialize the execution node or return to the list.";
$lang->zanode->initButton = "Initialize";
+28 -7
View File
@@ -42,12 +42,14 @@ $lang->zanode->vnc = 'VNC Port';
$lang->zanode->destroyAt = 'Destroy Time';
$lang->zanode->creater = 'Creator';
$lang->zanode->createdDate = 'Create Date';
$lang->zanode->confirmDelete = "Are you sure about destroying the ZenAgent Node?";
$lang->zanode->confirmBoot = "Are you sure to start the ZenAgent Node?";
$lang->zanode->confirmReboot = "Are you sure to restart the ZenAgent Node?";
$lang->zanode->confirmShutdown = "Are you sure to shutdown the ZenAgent Node?";
$lang->zanode->confirmSuspend = "Are you sure to suspend the ZenAgent Node?";
$lang->zanode->confirmResume = "Are you sure to resume the ZenAgent Node?";
$lang->zanode->confirmDelete = "Are you sure about destroying the ZenAgent Node?";
$lang->zanode->confirmBoot = "Are you sure to start the ZenAgent Node?";
$lang->zanode->confirmReboot = "Are you sure to restart the ZenAgent Node?";
$lang->zanode->confirmShutdown = "Are you sure to shutdown the ZenAgent Node?";
$lang->zanode->confirmSuspend = "Are you sure to suspend the ZenAgent Node?";
$lang->zanode->confirmResume = "Are you sure to resume the ZenAgent Node?";
$lang->zanode->confirmRestore = "Are you sure to restore the ZenAgent Node?";
$lang->zanode->confirmRestore = "The ZenAgent Node will be restored to this snapshot state, are you sure you want to continue?";
$lang->zanode->actionSuccess = 'Success';
$lang->zanode->deleted = "Deleted";
$lang->zanode->scriptPath = "Script path";
@@ -79,7 +81,25 @@ $lang->zanode->createImageSuccess = 'Successed, You can use this image to create
$lang->zanode->createImageFail = 'Failed to create';
$lang->zanode->createImageButton = 'Create image';
$lang->zanode->imageNameEmpty = 'Name can not be empty.';
$lang->zanode->snapshotName = 'Snapshot Name';
$lang->zanode->browseSnapshot = 'Snapshot List';
$lang->zanode->createSnapshot = 'Create Snapshot';
$lang->zanode->editSnapshot = 'Edit Snapshot';
$lang->zanode->restoreSnapshot = 'Revert Snapshot';
$lang->zanode->deleteSnapshot = 'Delete Snapshot';
$lang->zanode->snapshotEmpty = 'No snapshots';
$lang->zanode->confirmDeleteSnapshot = "The snapshot cannot be restored from the recycle bin after being deleted. Are you sure to continue?";
$lang->zanode->snapshot->statusList['creating'] = 'Creating';
$lang->zanode->snapshot->statusList['completed'] = 'Create Completed';
$lang->zanode->snapshot->statusList['failed'] = 'Create Failed';
$lang->zanode->snapshot->statusList['restoring'] = 'Restoring';
$lang->zanode->snapshot->statusList['restore_failed'] = 'Restore Failed';
$lang->zanode->snapshot->statusList['restore_completed'] = 'Restore Completed';
$lang->zanode->imageNameEmpty = 'Name can not be empty.';
$lang->zanode->snapStatusError = 'Snapshot is not ready.';
$lang->zanode->snapRestoring = 'Snapshot is restoring.';
$lang->zanode->runTimeout = 'Network connection timeout, please check the host and execution node status.';
@@ -101,6 +121,7 @@ $lang->zanode->statusList['shutodown'] = 'shutdown';
$lang->zanode->statusList['destroy_fail'] = 'Destroy Fail';
$lang->zanode->statusList['wait'] = 'Initializing';
$lang->zanode->statusList['online'] = 'Online';
$lang->zanode->statusList['restoring'] = 'Restoring';
$lang->zanode->initNotice = "Succeeded. Please initialize the execution node or return to the list.";
$lang->zanode->initButton = "Initialize";
+17
View File
@@ -79,6 +79,22 @@ $lang->zanode->createImageSuccess = 'Successed, You can use this image to create
$lang->zanode->createImageFail = 'Failed to create';
$lang->zanode->createImageButton = 'Create image';
$lang->zanode->snapshotName = 'Snapshot Name';
$lang->zanode->browseSnapshot = 'Snapshot List';
$lang->zanode->createSnapshot = 'Create Snapshot';
$lang->zanode->editSnapshot = 'Edit Snapshot';
$lang->zanode->restoreSnapshot = 'Revert Snapshot';
$lang->zanode->deleteSnapshot = 'Delete Snapshot';
$lang->zanode->snapshotEmpty = 'No snapshots';
$lang->zanode->confirmDeleteSnapshot = "The snapshot cannot be restored from the recycle bin after being deleted. Are you sure to continue?";
$lang->zanode->snapshot->statusList['creating'] = 'Creating';
$lang->zanode->snapshot->statusList['completed'] = 'Create Completed';
$lang->zanode->snapshot->statusList['failed'] = 'Create Failed';
$lang->zanode->snapshot->statusList['restoring'] = 'Restoring';
$lang->zanode->snapshot->statusList['restore_failed'] = 'Restore Failed';
$lang->zanode->snapshot->statusList['restore_completed'] = 'Restore Completed';
$lang->zanode->imageNameEmpty = 'Name can not be empty.';
$lang->zanode->runTimeout = 'Network connection timeout, please check the host and execution node status.';
@@ -101,6 +117,7 @@ $lang->zanode->statusList['shutodown'] = 'shutdown';
$lang->zanode->statusList['destroy_fail'] = 'Destroy Fail';
$lang->zanode->statusList['wait'] = 'Initializing';
$lang->zanode->statusList['online'] = 'Online';
$lang->zanode->statusList['restoring'] = 'Restoring';
$lang->zanode->initNotice = "Succeeded. Please initialize the execution node or return to the list.";
$lang->zanode->initButton = "Initialize";
+21
View File
@@ -48,6 +48,7 @@ $lang->zanode->confirmReboot = "您确定重启执行节点吗?";
$lang->zanode->confirmShutdown = "您确定关闭执行节点吗?";
$lang->zanode->confirmSuspend = "您确定休眠执行节点吗?";
$lang->zanode->confirmResume = "您确定恢复执行节点吗?";
$lang->zanode->confirmRestore = "执行节点将会还原至此快照状态,您确定要继续么?";
$lang->zanode->actionSuccess = '操作成功';
$lang->zanode->deleted = "已删除";
$lang->zanode->scriptPath = "脚本目录";
@@ -79,7 +80,26 @@ $lang->zanode->createImageSuccess = '镜像导出成功,您可以使用此镜
$lang->zanode->createImageFail = '镜像导出失败';
$lang->zanode->createImageButton = '去创建';
$lang->zanode->snapshotName = '快照名称';
$lang->zanode->browseSnapshot = '快照列表';
$lang->zanode->createSnapshot = '创建快照';
$lang->zanode->editSnapshot = '编辑快照';
$lang->zanode->restoreSnapshot = '还原快照';
$lang->zanode->deleteSnapshot = '删除快照';
$lang->zanode->snapshotEmpty = '无快照';
$lang->zanode->confirmDeleteSnapshot = "快照被删除后无法从回收站中还原,您确定继续么?";
$lang->zanode->snapshot->statusList['creating'] = '创建中';
$lang->zanode->snapshot->statusList['completed'] = '创建完成';
$lang->zanode->snapshot->statusList['failed'] = '创建失败';
$lang->zanode->snapshot->statusList['restoring'] = '还原中';
$lang->zanode->snapshot->statusList['restore_failed'] = '还原失败';
$lang->zanode->snapshot->statusList['restore_completed'] = '还原成功';
$lang->zanode->imageNameEmpty = '名称不能为空';
$lang->zanode->imageNameEmpty = '名称不能为空';
$lang->zanode->snapStatusError = '快照不可用';
$lang->zanode->snapRestoring = '快照正在还原中';
$lang->zanode->runTimeout = '自动执行失败,请检查宿主机和执行节点状态';
@@ -101,6 +121,7 @@ $lang->zanode->statusList['shutodown'] = '已关机';
$lang->zanode->statusList['destroy_fail'] = '销毁失败';
$lang->zanode->statusList['wait'] = '初始化中';
$lang->zanode->statusList['online'] = '已上架';
$lang->zanode->statusList['restoring'] = '还原中';
$lang->zanode->initNotice = "保存成功,请初始化执行节点或返回列表。";
$lang->zanode->initButton = "去初始化";
+193 -1
View File
@@ -28,6 +28,10 @@ class zanodemodel extends model
const KVM_EXPORT_PATH = '/api/v1/kvm/exportVm';
const KVM_STATUS_PATH = '/api/v1/task/getStatus';
const SNAPSHOT_CREATE_PATH = '/api/v1/kvm/addCreateSnap';
const SNAPSHOT_REVERT_PATH = '/api/v1/kvm/addRevertSnap';
const SNAPSHOT_REMOVE_PATH = '/api/v1/kvm/removeSnap';
/**
* Set lang;
*
@@ -167,6 +171,173 @@ class zanodemodel extends model
return false;
}
/**
* Create Snapshot by zanode.
*
* @param int $zanodeID
* @access public
* @return void
*/
public function createSnapshot($zanodeID = 0)
{
$data = fixer::input('post')->get();
if(empty($data->name)) dao::$errors['name'] = $this->lang->zanode->imageNameEmpty;
if(dao::isError()) return false;
$node = $this->getNodeByID($zanodeID);
$newSnapshot = new stdClass();
$newSnapshot->host = $node->id;
$newSnapshot->name = $data->name;
$newSnapshot->desc = $data->desc;
$newSnapshot->status = 'creating';
$newSnapshot->osName = $node->osName;
$newSnapshot->from = 'snapshot';
$newSnapshot->createdBy = $this->app->user->account;
$newSnapshot->createdDate = helper::now();
$this->dao->insert(TABLE_IMAGE)
->data($newSnapshot)
->autoCheck()
->exec();
if(dao::isError()) return false;
$newID = $this->dao->lastInsertID();
/* Prepare create params. */
$agnetUrl = 'http://' . $node->ip . ':' . $node->hzap;
$param = array(array(
'name' => $data->name,
'task' => $newID,
'type' => 'createSnap',
'vm' => $node->name
));
$result = json_decode(commonModel::http($agnetUrl . static::SNAPSHOT_CREATE_PATH, json_encode($param,JSON_NUMERIC_CHECK), null, array("Authorization:$node->tokenSN")));
if(!empty($result) and $result->code == 'success')
{
$this->loadModel('action')->create('zanode', $zanodeID, 'createdSnapshot', '', $data->name);
return $newID;
}
$this->dao->delete()->from(TABLE_IMAGE)->where('id')->eq($newID)->exec();
dao::$errors[] = (!empty($result) and !empty($result->msg)) ? $result->msg : $this->app->lang->fail;
return false;
}
/**
* Edit Snapshot.
*
* @param int $snapshotID
* @access public
* @return bool
*/
public function editSnapshot($snapshotID)
{
$data = fixer::input('post')->get();
if(empty($data->name)) dao::$errors['name'] = $this->lang->zanode->imageNameEmpty;
if(dao::isError()) return false;
$newSnapshot = new stdClass();
$newSnapshot->localName = $data->name;
$newSnapshot->desc = $data->desc;
$this->dao->update(TABLE_IMAGE)
->data($newSnapshot)
->where('id')->eq($snapshotID)
->autoCheck()
->exec();
return true;
}
/**
* Restore Snapshot to zanode.
*
* @param int $zanodeID
* @access public
* @return void
*/
public function restoreSnapshot($zanodeID = 0, $snapshotID = 0)
{
$node = $this->getNodeByID($zanodeID);
$snap = $this->getImageByID($snapshotID);
$snap->status = ($snap->status == 'restoring' && time() - strtotime($snap->restoreDate) > 600) ? 'restore_failed' : $snap->status;
if(!in_array($snap->status, array('completed', 'restoring', 'restore_failed', 'restore_completed'))) dao::$errors = $this->lang->zanode->snapStatusError;
if($snap->status == 'restoring') dao::$errors = $this->lang->zanode->snapRestoring;
if(dao::isError()) return false;
//update snapshot status
$this->dao->update(TABLE_IMAGE)
->set('status')->eq('restoring')
->set('restoreDate')->eq(helper::now())
->where('id')->eq($snapshotID)->exec();
/* Prepare create params. */
$agnetUrl = 'http://' . $node->ip . ':' . $node->hzap;
$param = array(array(
'name' => $snap->name,
'task' => $snapshotID,
'type' => 'revertSnap',
'vm' => $node->name
));
$result = json_decode(commonModel::http($agnetUrl . static::SNAPSHOT_CREATE_PATH, json_encode($param,JSON_NUMERIC_CHECK), null, array("Authorization:$node->tokenSN")));
if(!empty($result) and $result->code == 'success')
{
$this->dao->update(TABLE_HOST)->set('status')->eq('restoring')->where('id')->eq($node->id)->exec();
$this->loadModel('action')->create('zanode', $zanodeID, 'restoredsnapshot', '', $snap->name);
return true;
}
$this->dao->update(TABLE_IMAGE)->set('status')->eq('completed')->where('id')->eq($snapshotID)->exec();
dao::$errors[] = (!empty($result) and !empty($result->msg)) ? $result->msg : $this->lang->zanode->apiError['fail'];
return false;
}
/**
* Delete Snapshot.
*
* @param int $id
* @access public
* @return void
*/
public function deleteSnapshot($snapshotID)
{
$snapshot = $this->getImageByID($snapshotID);
$node = $this->getNodeByID($snapshot->host);
if($node)
{
$agnetUrl = 'http://' . $node->ip . ':' . $node->hzap;
$param = (object)array(
'name' => $snapshot->name,
'task' => $snapshotID,
'vm' => $node->name
);
$result = commonModel::http($agnetUrl . static::SNAPSHOT_REMOVE_PATH, json_encode($param,JSON_NUMERIC_CHECK), array(), array("Authorization:$node->tokenSN"));
$result = json_decode($result);
if(!empty($result) and $result->code == 'success')
{
$this->dao->delete()->from(TABLE_IMAGE)->where('id')->eq($snapshotID)->exec();
$this->loadModel('action')->create('zanode', $node->id, 'deletesnapshot', '', $snapshot->name);
return true;
}
$error = (!empty($result) and !empty($result->msg)) ? $result->msg : $this->lang->zanode->apiError['fail'];
return $error;
}
}
/**
* Action Node.
*
@@ -212,7 +383,7 @@ class zanodemodel extends model
public function destroy($id)
{
$node = $this->getNodeByID($id);
if($node)
{
$req = array( 'name' => $node->name );
@@ -520,6 +691,27 @@ class zanodemodel extends model
->fetch();
}
public function getSnapshotList($nodeID, $browseType = 'all', $param = 0, $orderBy = 'id', $pager = null)
{
$snapshotList = $this->dao->select('*')->from(TABLE_IMAGE)
->where('host')->eq($nodeID)
->andWhere('`from`')->eq('snapshot')
->orderBy($orderBy)
->page($pager)
->fetchAll('name');
foreach($snapshotList as $name => $snapshot)
{
if($snapshot->status == 'creating' and (time() - strtotime($snapshot->createdDate)) > 1800)
{
$this->dao->update(TABLE_IMAGE)->set('status')->eq('failed')->where('id')->eq($snapshot->id)->exec();
$snapshotList[$name]->status = 'failed';
}
}
return $snapshotList;
}
/**
* Get Node by id.
*
+5 -1
View File
@@ -85,6 +85,9 @@
$rebootAttr = "title='{$lang->zanode->reboot}' target='hiddenwin'";
$rebootAttr .= $node->status == 'shutoff' ? ' class="btn disabled"' : "class='btn' target='hiddenwin' onclick='if(confirm(\"{$lang->zanode->confirmReboot}\")==false) return false;'";
$snapshotAttr = "title='{$lang->zanode->createSnapshot}'";
$snapshotAttr .= $node->status != 'running' ? ' class="btn disabled"' : ' class="btn iframe"';
common::printLink('zanode', 'getVNC', "id={$node->id}", "<i class='icon icon-remote'></i> ", (in_array($node->status ,array('running', 'launch', 'wait')) ? '_blank' : ''), "title='{$lang->zanode->getVNC}' class='btn desktop " . (in_array($node->status ,array('running', 'launch', 'wait')) ? '':'disabled') . "'", '');
if($node->status == "suspend")
{
@@ -105,13 +108,14 @@
}
common::printLink('zanode', 'reboot', "zanodeID={$node->id}", "<i class='icon icon-restart'></i> ", '', $rebootAttr);
common::printIcon('zanode', 'edit', "id={$node->id}", $node, 'list');
common::printLink('zanode', 'createSnapshot', "zanodeID={$node->id}", "<i class='icon icon-plus'></i> ", '', $snapshotAttr, true, true);
if(common::hasPriv('zanode', 'createImage') or common::hasPriv('zanode', 'destroy'))
{
echo "<div class='btn-group'>";
echo "<button type='button' class='btn dropdown-toggle' data-toggle='context-dropdown' title='{$this->lang->more}'><i class='icon-ellipsis-v'></i></button>";
echo "<ul class='dropdown-menu pull-right text-center' role='menu'>";
common::printIcon('zanode', 'edit', "id={$node->id}", $node, 'list', '', '', 'btn-action');
common::printLink('zanode', 'createImage', "zanodeID={$node->id}", "<i class='icon icon-export'></i> ", '', "class='btn btn-action iframe createImage' title='{$lang->zanode->createImage}' data-width='55%'", '', true);
common::printLink('zanode', 'destroy', "zanodeID={$node->id}", "<i class='icon icon-trash'></i> ", '', "title='{$lang->zanode->destroy}' class='btn btn-action' target='hiddenwin'");
echo "</ul>";
@@ -0,0 +1,66 @@
<?php
/**
* The snapshot browse view file of zahost module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author xiawenlong <liyuchun@easycorp.ltd>
* @package zahost
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<?php js::set('nodeID', $nodeID);?>
<div id='mainContent' class='main-table'>
<?php $vars = "nodeID=$nodeID&browseType=all&param=0&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}";?>
<?php if(empty($snapshotList)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->zanode->snapshotEmpty;?></span>
</p>
</div>
<?php else:?>
<table class='table has-sort-head table-fixed' id='snapshotList'>
<thead>
<tr>
<th class='c-name'><?php common::printOrderLink('name', $orderBy, $vars, $lang->zahost->image->name);?></th>
<th class='c-status'><?php echo $lang->zahost->status;?></th>
<th class='c-createdBy'><?php echo $lang->zahost->createdBy;?></th>
<th class='c-datetime'><?php echo $lang->zahost->createdDate;?></th>
<th class='c-actions-3'><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
<?php foreach($snapshotList as $snapshot):?>
<tr>
<?php
$snapshot->status = ($snapshot->status == 'restoring' && time() - strtotime($snapshot->restoreDate) > 600) ? 'restore_failed' : $snapshot->status;
$editAttr = $snapshot->status == 'failed' ? 'class="btn disabled"' : "title={$lang->zanode->editSnapshot} onclick='window.parent.editSnapshot(\"" . $this->createLink('zanode', 'editSnapshot', "snapshotID={$snapshot->id}") . "\")' class='btn'";
$restoreAttr = "title='{$lang->zanode->restoreSnapshot}' target='hiddenwin'";
$restoreAttr .= ($node->status !='running' or $snapshot->status == 'restoring' or $snapshot->status == 'failed') ? ' class="btn disabled"' : 'class="btn"';
$deleteAttr = "title='{$lang->zanode->deleteSnapshot}' target='hiddenwin'";
$deleteAttr .= (($snapshot->status == 'restoring' and (time() - strtotime($snapshot->restoreDate)) <= 600) or $snapshot->status == 'failed') ? ' class="btn disabled"' : 'class="btn"';
?>
<td title="<?php echo $snapshot->name;?>"><?php echo $snapshot->localName ? $snapshot->localName : $snapshot->name;?></td>
<td class='<?php echo $snapshot->status;?>'><?php echo zget($lang->zanode->snapshot->statusList, $snapshot->status, '');?></td>
<td class="c-createdBy"><?php echo zget($users, $snapshot->createdBy, '')?></td>
<td class='c-datetime'><?php echo $snapshot->createdDate;?></td>
<td class='c-actions'>
<?php if(common::hasPriv('zanode', 'editSnapshot')) echo html::a('###', '<i class="icon-edit"></i>', 'hiddenwin', $editAttr);?>
<?php if(common::hasPriv('zanode', 'restoreSnapshot')) echo html::a($this->createLink('zanode', 'restoreSnapshot', "nodeID={$nodeID}&snapshotID={$snapshot->id}"), '<i class="icon-restart"></i>', 'hiddenwin', $restoreAttr);?>
<?php if(common::hasPriv('zanode', 'deleteSnapshot')) echo html::a($this->createLink('zanode', 'deleteSnapshot', "snapshotID={$snapshot->id}"), '<i class="icon-trash"></i>', 'hiddenwin', $deleteAttr);?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='table-footer'>
<?php $pager->show('right', 'pagerjs');?>
</div>
<?php endif;?>
</div>
<?php include $app->getModuleRoot() . 'common/view/footer.html.php';?>
@@ -0,0 +1,46 @@
<?php
/**
* The create file of snapshot of zanode.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author chunsheng wang <chunsheng@cnezsoft.com>
* @package task
* @version
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('nodeID', $node->id);?>
<?php js::set('zanodeLang', $lang->zanode); ?>
<style>.body-modal #mainContent{width:90%}
</style>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2>
<span><?php echo $lang->zanode->createSnapshot;?></span>
</h2>
</div>
<form class="load-indicator main-form form-ajax" method='post' enctype='multipart/form-data' id='dataform'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->zanode->snapshotName;?></th>
<td class='required'><?php echo html::input('name', '', "class='form-control'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->zanode->desc;?></th>
<td colspan='2'><?php echo html::textarea('desc', '', "rows='6' class='form-control'");?></td>
</tr>
<tr>
<td colspan='3' class='text-center'>
<?php echo html::submitButton('', "");?>
</td>
</tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+45
View File
@@ -0,0 +1,45 @@
<?php
/**
* The edit file of snapshot of zanode.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author chunsheng wang <chunsheng@cnezsoft.com>
* @package task
* @version
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('zanodeLang', $lang->zanode); ?>
<style>.body-modal #mainContent{width:90%}
</style>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2>
<span><?php echo $lang->zanode->editSnapshot;?></span>
</h2>
</div>
<form class="load-indicator main-form form-ajax" method='post' enctype='multipart/form-data' id='dataform'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->zanode->snapshotName;?></th>
<td class='required'><?php echo html::input('name', $snapshot->localName ? $snapshot->localName : $snapshot->name, "class='form-control'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->zanode->desc;?></th>
<td colspan='2'><?php echo html::textarea('desc', $snapshot->desc, "rows='6' class='form-control'");?></td>
</tr>
<tr>
<td colspan='3' class='text-center'>
<?php echo html::submitButton('', "");?>
</td>
</tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>

Some files were not shown because too many files have changed in this diff Show More