diff --git a/module/admin/config.php b/module/admin/config.php
index 94961a2238..64555329fb 100755
--- a/module/admin/config.php
+++ b/module/admin/config.php
@@ -83,6 +83,7 @@ $config->admin->helpURL['message'] = 'https://www.zentao.net/book/zentaopms/em
$config->admin->helpURL['extension'] = 'https://www.zentao.net/book/zentaopms/536.html';
$config->admin->helpURL['dev'] = 'https://www.zentao.net/book/zentaopms/537.html';
$config->admin->helpURL['convert'] = 'https://www.zentao.net/book/zentaopms/656.html';
+$config->admin->helpURL['platform'] = 'https://www.zentao.net/book/zentaopms/656.html';
$config->admin->navsGroup['feature']['my'] = ',todo,block,';
$config->admin->navsGroup['feature']['product'] = ',product,story,productplan,release,';
diff --git a/module/admin/control.php b/module/admin/control.php
index 7705fca59f..4299595e76 100755
--- a/module/admin/control.php
+++ b/module/admin/control.php
@@ -543,4 +543,36 @@ class admin extends control
return print(json_encode($response));
}
+
+ /**
+ * AJAX: Get drop menu.
+ *
+ * @param string $currentMenuKey
+ * @access public
+ * @return void
+ */
+ public function ajaxGetDropMenu($currentMenuKey = '')
+ {
+ $this->admin->checkPrivMenu();
+ $data = array();
+ foreach($this->lang->admin->menuList as $menuKey => $menuGroup)
+ {
+ if($this->config->vision == 'lite' and !in_array($menuKey, $this->config->admin->liteMenuList)) continue;
+ $data[] = array(
+ 'id' => $menuKey,
+ 'name' => $menuKey,
+ 'content' => array('html' => "

{$menuGroup['name']}
"),
+ 'text' => '',
+ 'title' => $menuGroup['name'],
+ 'type' => 'item',
+ 'url' => $menuGroup['disabled'] ? '' : $menuGroup['link'],
+ 'active' => $currentMenuKey == $menuKey,
+ 'rootClass' => 'admin-menu-item',
+ 'attrs' => array('disabled' => $menuGroup['disabled'])
+ );
+ }
+
+ $this->view->data = $data;
+ $this->display();
+ }
}
diff --git a/module/admin/lang/menu.php b/module/admin/lang/menu.php
index 6c41a5b1d6..c1be2498f9 100644
--- a/module/admin/lang/menu.php
+++ b/module/admin/lang/menu.php
@@ -46,7 +46,6 @@ $lang->admin->menuList->convert['order'] = 50;
$lang->admin->menuList->platform['name'] = $lang->admin->menuSetting['platform']['name'];
$lang->admin->menuList->platform['desc'] = $lang->admin->menuSetting['platform']['desc'];
-$lang->admin->menuList->platform['link'] = 'system|browsebackup';
$lang->admin->menuList->platform['order'] = 55;
$lang->admin->menuList->system['subMenu']['mode'] = array('link' => "{$lang->custom->mode}|custom|mode|");
diff --git a/module/admin/ui/index.html.php b/module/admin/ui/index.html.php
deleted file mode 100755
index 84da77023b..0000000000
--- a/module/admin/ui/index.html.php
+++ /dev/null
@@ -1,381 +0,0 @@
-
- * @package admin
- * @link https://www.zentao.net
- */
-
-namespace zin;
-
-/* Get latest data from zentao.net if ZenTaoPMS has internet and the user is admin. */
-jsVar('hasInternet', $zentaoData->hasData || $hasInternet);
-jsVar('isAdminUser', $this->app->user->admin);
-
-$buildHeader = function(string $title, string $actionUrl = '', string $titleIcon = '', string $actionLang = '', string $actionIcon = ''): h
-{
- global $lang;
-
- return div
- (
- setClass('flex justify-between items-center pl-4 h-10'),
- div
- (
- setClass('panel-title'),
- $titleIcon ? icon
- (
- setClass('text-lg text-primary pr-1'),
- $titleIcon
- ) : null,
- $title
- ),
- $actionUrl ? a
- (
- setClass('text-gray pr-3'),
- set::target('_blank'),
- set::href($actionUrl),
- $actionLang ? $actionLang : $lang->more,
- icon($actionIcon ? $actionIcon : 'caret-right')
- ) : null
- );
-};
-
-$buildPluginHeader = function($name, $url): h
-{
- return div
- (
- setClass('flex justify-between items-center'),
- div
- (
- setClass('panel-title py-2.5'),
- $name,
- ),
- a
- (
- //setClass('flex items-center'),
- set::href($url),
- set::target('_blank'),
- icon
- (
- setClass('text-primary bg-primary-100 p-1'),
- 'download-alt'
- )
- )
- );
-};
-
-$buildUsed = function(int $amount, string $unit = ''): array
-{
- return array
- (
- $amount ? span
- (
- setClass('bg-lighter rounded-md text-lg mx-1 px-1 py-0.5'),
- $amount
- ) : null,
- $amount ? $unit : ''
- );
-};
-
-$settingItems = array();
-foreach($lang->admin->menuList as $menuKey => $menu)
-{
- if($config->vision == 'lite' and !in_array($menuKey, $config->admin->liteMenuList)) continue;
-
- $link = '';
- if(!empty($menu['link'])) $link = $menu['link'];
- if(!empty($menu['subMenu']))
- {
- foreach($menu['subMenu'] as $subMenu)
- {
- if(!empty($subMenu['link']))
- {
- $link = $subMenu['link'];
- break;
- }
- }
- }
-
- $params = explode('|', $link);
- if(count($params) == 2) list($module, $method) = $params;
- if(count($params) > 2) list($label, $module, $method) = $params;
-
- $url = $module && $method ? createLink($module, $method) : '';
-
- $settingItems[] = div
- (
- setClass('pb-4 pr-4 w-1/5 h-32'),
- col
- (
- setClass('setting-box cursor-pointer border border-hover rounded-md px-2 py-1 h-full'),
- set(array('data-id' => $menuKey, 'data-url' => $url)),
- !empty($menu['disabled']) ? set::title($lang->admin->noPriv) : null,
- h4
- (
- setClass('flex my-2.5 w-full'),
- div
- (
- setClass('flex gap-1 font-bold text-md'),
- img(set::src("static/svg/admin-{$menuKey}.svg")),
- $menu['name'],
- a
- (
- setClass('text-gray'),
- set::href($config->admin->helpURL[$menuKey]),
- set::title($lang->help),
- set::target('_blank'),
- icon('help'),
- )
- ),
- ),
- p
- (
- setClass('overflow-hidden text-left text-gray pb-4 h-12 leading-6'),
- set::title($menu['desc']),
- $menu['desc']
- )
- )
- );
-}
-
-$pluginItems = array();
-if($zentaoData->plugins)
-{
- foreach($zentaoData->plugins as $plugin)
- {
- $pluginDesc = preg_replace('/[[:cntrl:]]/mu', '', strip_tags($plugin->abstract));
-
- $pluginItems[] = div
- (
- setClass('pr-4 pb-4 w-1/3 h-32'),
- div
- (
- setClass('border rounded-md px-3 py-2'),
- $buildPluginHeader($plugin->name, $plugin->viewLink),
- div
- (
- setClass('overflow-hidden text-gray h-12 leading-6'),
- set::title($pluginDesc),
- $pluginDesc
- )
- )
- );
- }
-}
-
-$classItems = array();
-if($zentaoData->classes)
-{
- foreach($zentaoData->classes as $class)
- {
- $classItems[] = a
- (
- setClass('border border-hover rounded-md mr-4 mb-4 p-1 w-1/3'),
- set::href($class->viewLink),
- set::target('_blank'),
- img
- (
- set::src($class->image)
- ),
- div
- (
- setClass('overflow-hidden text-md text-center font-bold text-black mb-1.5 p-1 h-6'),
- $class->name
- )
- );
- }
-}
-
-$dynamicItems = array();
-foreach($zentaoData->dynamics as $dynamic)
-{
- $dynamicItems[] = div
- (
- setClass('relative flex justify-between border-t px-4 py-3 h-18'),
- div
- (
- setClass('overflow-hidden h-12 leading-normal'),
- set::title($dynamic->title),
- icon
- (
- setClass('text-lg text-primary pr-1'),
- 'horn'
- ),
- a
- (
- setClass('text-black'),
- set::href($dynamic->link),
- set::target('_blank'),
- $dynamic->title
- )
- ),
- div
- (
- setClass('absolute nowrap right-3 bottom-3 pl-2.5 pr-3'),
- substr($dynamic->addedDate, 0, 10)
- )
- );
-}
-
-$patchItems = array();
-foreach($zentaoData->patches as $patch)
-{
- $patchItems[] = div
- (
- setClass('border-t pt-2.5 pb-3 px-4'),
- $buildPluginHeader($patch->name, $patch->viewLink),
- div
- (
- setClass('overflow-hidden h-10'),
- $patch->desc
- )
- );
-}
-
-$upgradeItems = array();
-foreach(array('biz', 'max') as $edition)
-{
- $featureItems = array();
- foreach($lang->admin->productFeature[$edition] as $feature)
- {
- $featureItems[] = div
- (
- setClass('flex items-center my-1 pl-5 h-5'),
- div
- (
- setClass('rounded-full light mr-2 w-2 h-2')
- ),
- $feature
- );
- }
-
- $upgradeItems[] = div
- (
- setClass('border-t py-1.5'),
- $buildHeader($lang->admin->{$edition . 'Tag'} , $config->admin->apiRoot, 'zentao', $lang->admin->productDetail),
- $featureItems
- );
-}
-
-div
-(
- set::style(array('width' => '70%')),
- div
- (
- setID('settings'),
- setClass('bg-white rounded-md mb-4'),
- $buildHeader($lang->admin->setting),
- div
- (
- setClass('flex flex-wrap pl-4'),
- on::click('redirectSetting'),
- $settingItems
- )
- ),
- $pluginItems ? div
- (
- setID('plugin'),
- setClass('bg-white rounded-md mb-4'),
- $buildHeader($lang->admin->pluginRecommendation, $config->admin->extensionURL),
- div
- (
- setClass('flex flex-wrap pl-4'),
- $pluginItems
- )
- ) : null,
- div
- (
- setClass('flex'),
- div
- (
- setClass('bg-white rounded-md mb-4 w-1/3'),
- $buildHeader($lang->admin->officialAccount),
- div
- (
- setClass('flex px-4'),
- img
- (
- setClass('w-1/3'),
- set::src('static/images/wechat.jpg')
- ),
- div
- (
- setClass('pl-2 w-2/3'),
- $lang->admin->followUs,
- div
- (
- setClass('text-gray'),
- $lang->admin->followUsContent
- )
- )
- ),
- div
- (
- setClass('px-4 pb-4'),
- substr($lang->admin->notice->register, 0, strpos($lang->admin->notice->register, '%s')),
- a
- (
- set::href(inlink('register')),
- $lang->admin->registerNotice->submitHere
- ),
- substr($lang->admin->notice->register, strpos($lang->admin->notice->register, '%s') + 2),
- )
- ),
- div
- (
- setClass('bg-white rounded-md ml-4 mb-4 w-2/3'),
- $buildHeader($lang->admin->publicClass, $config->admin->classURL),
- div
- (
- setClass('flex pl-4'),
- $classItems
- )
- )
- )
-);
-
-div
-(
- setClass('bg-white rounded-md ml-4 px-4'),
- set::style(array('width' => '30%')),
- div
- (
- setClass('flex justify-between items-center h-14'),
- div
- (
- setClass('panel-title text-md py-2.5'),
- $lang->admin->zentaoInfo
- ),
- div
- (
- setStyle(array('letter-spacing' => '1px')),
- $lang->admin->zentaoUsed,
- $buildUsed((int)$dateUsed->year, $lang->year),
- $buildUsed((int)$dateUsed->month, $lang->admin->mon),
- $buildUsed((int)$dateUsed->day, $lang->admin->day)
- )
- ),
- div
- (
- setClass('border rounded-md mb-4'),
- $buildHeader($lang->admin->updateDynamics, $config->admin->dynamicURL),
- $dynamicItems,
- ),
- div
- (
- setClass('border rounded-md mb-4'),
- $buildHeader($lang->admin->updatePatch, $config->admin->patchURL),
- $patchItems
- ),
- div
- (
- setClass('border rounded-md mb-4'),
- $buildHeader($lang->admin->upgradeRecommend),
- $upgradeItems
- )
-);
-
-render();
diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php
index 75f7523481..43c2697953 100644
--- a/module/common/lang/menu.php
+++ b/module/common/lang/menu.php
@@ -53,7 +53,7 @@ $lang->mainNav->product = "{$lang->navIcons['product']} {$lang->productCommon}
$lang->mainNav->project = "{$lang->navIcons['project']} {$lang->projectCommon}|$projectModule|$projectMethod|";
$lang->mainNav->execution = "{$lang->navIcons['execution']} {$lang->execution->common}|$executionModule|$executionMethod|";
$lang->mainNav->qa = "{$lang->navIcons['qa']} {$lang->qa->common}|qa|index|";
-$lang->mainNav->devops = "{$lang->navIcons['devops']} DevOps|repo|browse|";
+$lang->mainNav->devops = "{$lang->navIcons['devops']} DevOps|repo|maintain|";
$lang->mainNav->kanban = "{$lang->navIcons['kanban']} {$lang->kanban->common}|kanban|space|";
$lang->mainNav->doc = "{$lang->navIcons['doc']} {$lang->doc->common}|doc|index|";
$lang->mainNav->bi = "{$lang->navIcons['bi']} {$lang->bi->common}|screen|browse|";
@@ -482,29 +482,36 @@ $lang->qa->menuOrder[45] = 'automation';
$lang->qa->dividerMenu = ',bug,testtask,caselib,automation,';
/* DevOps menu. */
+$lang->devops->homeMenu = new stdclass();
+//$lang->devops->homeMenu->dashboard = array('link' => "{$lang->dashboard}|system|dashboard");
+$lang->devops->homeMenu->repos = array('link' => "{$lang->devops->repo}|repo|maintain", 'alias' => 'create,edit,import');
+$lang->devops->homeMenu->compile = array('link' => "{$lang->devops->compile}|job|browse", 'subModule' => 'compile,job');
+$lang->devops->homeMenu->WIPs = array('link' => "{$lang->app->common}|space|browse", 'subModule' => 'instance,store,gitlab,gitea,gogs', 'alias' => 'createapplication,binduser,edit');
+//$lang->devops->homeMenu->environment = array('link' => "{$lang->devops->environment}|gitlab|browse", 'subModule' => 'gitlab,jenkins,sonarqube,gitea,gogs', 'alias' => 'setrules,create,edit,import');
+//$lang->devops->homeMenu->app = array('link' => "{$lang->app->common}|app|serverlink|%s");
+
$lang->devops->menu = new stdclass();
$lang->devops->menu->code = array('link' => "{$lang->repo->common}|repo|browse|repoID=%s", 'alias' => 'diff,view,revision,log,blame,showsynccommit');
$lang->devops->menu->mr = array('link' => "{$lang->devops->mr}|mr|browse|repoID=%s");
$lang->devops->menu->compile = array('link' => "{$lang->devops->compile}|job|browse|repoID=%s", 'subModule' => 'compile,job');
-$lang->devops->menu->app = array('link' => "{$lang->app->common}|app|serverlink|%s");
-$lang->devops->menu->set = array('link' => "{$lang->devops->set}|repo|maintain", 'subModule' => 'gitlab,jenkins,sonarqube,gitea,gogs', 'alias' => 'setrules,create,edit,import');
-$lang->devops->menuOrder[5] = 'code';
-$lang->devops->menuOrder[10] = 'mr';
-$lang->devops->menuOrder[15] = 'compile';
-$lang->devops->menuOrder[20] = 'app';
-$lang->devops->menuOrder[25] = 'set';
+//$lang->devops->menuOrder[5] = 'dashboard';
+$lang->devops->menuOrder[10] = 'repos';
+$lang->devops->menuOrder[15] = 'code';
+$lang->devops->menuOrder[20] = 'mr';
+$lang->devops->menuOrder[25] = 'compile';
+$lang->devops->menuOrder[30] = 'WIPs';
+//$lang->devops->menuOrder[35] = 'environment';
+//$lang->devops->menuOrder[40] = 'app';
-$lang->devops->dividerMenu = ',set,';
+$lang->devops->dividerMenu = ',WIPs,';
-$lang->devops->menu->set['subMenu'] = new stdclass();
-$lang->devops->menu->set['subMenu']->repo = array('link' => "{$lang->devops->repo}|repo|maintain", 'alias' => 'create,edit,import');
-$lang->devops->menu->set['subMenu']->gitlab = array('link' => 'GitLab|gitlab|browse', 'subModule' => 'gitlab');
-$lang->devops->menu->set['subMenu']->gogs = array('link' => 'Gogs|gogs|browse', 'subModule' => 'gogs');
-$lang->devops->menu->set['subMenu']->gitea = array('link' => 'Gitea|gitea|browse', 'subModule' => 'gitea');
-$lang->devops->menu->set['subMenu']->jenkins = array('link' => 'Jenkins|jenkins|browse', 'subModule' => 'jenkins');
-$lang->devops->menu->set['subMenu']->sonarqube = array('link' => 'SonarQube|sonarqube|browse', 'subModule' => 'sonarqube');
-$lang->devops->menu->set['subMenu']->setrules = array('link' => "{$lang->devops->rules}|repo|setrules");
+$lang->devops->homeMenu->environment['subMenu'] = new stdclass();
+$lang->devops->homeMenu->environment['subMenu']->gitlab = array('link' => 'GitLab|gitlab|browse', 'subModule' => 'gitlab');
+$lang->devops->homeMenu->environment['subMenu']->gogs = array('link' => 'Gogs|gogs|browse', 'subModule' => 'gogs');
+$lang->devops->homeMenu->environment['subMenu']->gitea = array('link' => 'Gitea|gitea|browse', 'subModule' => 'gitea');
+$lang->devops->homeMenu->environment['subMenu']->jenkins = array('link' => 'Jenkins|jenkins|browse', 'subModule' => 'jenkins');
+$lang->devops->homeMenu->environment['subMenu']->sonarqube = array('link' => 'SonarQube|sonarqube|browse', 'subModule' => 'sonarqube');
/* Kanban menu. */
$lang->kanban->menu = new stdclass();
@@ -722,6 +729,7 @@ $lang->navGroup->featureconfig = 'admin';
$lang->navGroup->doctemplate = 'admin';
$lang->navGroup->notifysetting = 'admin';
$lang->navGroup->holidayseason = 'admin';
+$lang->navGroup->system = 'admin';
$lang->navGroup->index = 'index';
$lang->navGroup->misc = 'misc';
diff --git a/module/system/ui/editdomain.html.php b/module/system/ui/editdomain.html.php
index 09dbf9d75f..dd3b275f3f 100644
--- a/module/system/ui/editdomain.html.php
+++ b/module/system/ui/editdomain.html.php
@@ -19,6 +19,7 @@ formPanel
formGroup
(
set::label($lang->system->domain->oldDomain),
+ set::name(''),
set::control('static'),
set::value($this->loadModel('cne')->sysDomain()),
h::span