* Merge 18 devopos to 20

This commit is contained in:
zenggang
2023-10-07 03:03:28 +00:00
parent 4e535ae301
commit 10a61396a1
196 changed files with 3646 additions and 940 deletions
+2
View File
@@ -142,6 +142,8 @@ CREATE TABLE `zt_artifactrepo` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `zt_repo` ADD `lastCommit` DATETIME NULL DEFAULT NULL AFTER `lastSync`;
ALTER TABLE `zt_build` ADD `artifactRepoID` MEDIUMINT(8) UNSIGNED NOT NULL AFTER `bugs`;
CREATE TABLE IF NOT EXISTS `zt_session` (
+1
View File
@@ -1482,6 +1482,7 @@ CREATE TABLE IF NOT EXISTS `zt_repo` (
`acl` text NULL,
`synced` tinyint(1) NOT NULL DEFAULT '0',
`lastSync` datetime NULL,
`lastCommit` datetime NULL,
`desc` text NULL,
`extra` char(30) NOT NULL DEFAULT '',
`preMerge` enum('0','1') COLLATE 'utf8_general_ci' NOT NULL DEFAULT '0',
+3 -8
View File
@@ -322,14 +322,9 @@ class Gitea
if(strpos($fromRevision, '^') !== false)
{
$list = execCmd(escapeCmd("$this->client log -2 $toRevision --pretty=format:%H -- $path"), 'array');
if(isset($list[1]))
{
$fromRevision = $list[1];
}
else
{
$fromRevision = 'HEAD^';
}
if(!isset($list[1])) return execCmd(escapeCmd("$this->client show HEAD"), 'array');
$fromRevision = $list[1];
}
$lines = execCmd(escapeCmd("$this->client diff $fromRevision $toRevision -- $path"), 'array');
return $lines;
+29 -6
View File
@@ -575,7 +575,7 @@ class gitlab
$log->time = date('Y-m-d H:i:s', strtotime($commit->created_at));
$commits[$commit->id] = $log;
$files[$commit->id] = $this->getFilesByCommit($log->revision);
if($getFile) $files[$commit->id] = $this->getFilesByCommit($log->revision);
return array('commits' => $commits, 'files' => $files);
}
@@ -659,7 +659,7 @@ class gitlab
* @access public
* @return array
*/
public function getCommitsByPath($path, $fromRevision = '', $toRevision = '', $perPage = 0, $page = 1, $getUrl = false)
public function getCommitsByPath($path, $fromRevision = '', $toRevision = '', $perPage = 0, $page = 1, $getUrl = false, $beginDate = '', $endDate = '')
{
$path = ltrim($path, DIRECTORY_SEPARATOR);
$api = "commits";
@@ -668,17 +668,17 @@ class gitlab
$param->path = urldecode($path);
$param->ref_name = ($toRevision != 'HEAD' and $toRevision) ? $toRevision : $this->branch;
$fromDate = $this->getCommittedDate($fromRevision);
$toDate = $this->getCommittedDate($toRevision);
$fromDate = $beginDate ? $beginDate : $this->getCommittedDate($fromRevision);
$toDate = $endDate ? $endDate : $this->getCommittedDate($toRevision);
$since = '';
$until = '';
if($fromRevision and $toRevision)
if(($fromRevision && $toRevision) || ($beginDate && $endDate))
{
$since = min($fromDate, $toDate);
$until = max($fromDate, $toDate);
}
elseif($fromRevision)
elseif($fromRevision || $beginDate)
{
$since = $fromDate;
}
@@ -949,4 +949,27 @@ class gitlab
}
return $lists;
}
/**
* 获取特定对象的api。
* Get api url for target.
*
* @param string $target
* @access public
* @return string
*/
public function getApiUrl(string $target): string
{
if($target == 'project')
{
return str_replace('repository/', '', $this->root). "?private_token={$this->token}";
}
$params = array();
$params['private_token'] = $this->token;
$params['page'] = 1;
$params['per_page'] = isset($params['per_page']) ? $params['per_page'] : 100;
$api = $this->root . $target . '?' . http_build_query($params);
return $api;
}
}
+3 -1
View File
@@ -310,7 +310,9 @@ class GitRepo
if(strpos($fromRevision, '^') !== false)
{
$list = execCmd(escapeCmd("$this->client log -2 $toRevision --pretty=format:%H -- $path"), 'array');
if(isset($list[1])) $fromRevision = $list[1];
if(!isset($list[1])) return execCmd(escapeCmd("$this->client show HEAD"), 'array');
$fromRevision = $list[1];
}
$lines = execCmd(escapeCmd("$this->client diff $fromRevision $toRevision -- $path"), 'array');
return $lines;
+3 -1
View File
@@ -322,7 +322,9 @@ class Gogs
if(strpos($fromRevision, '^') !== false)
{
$list = execCmd(escapeCmd("$this->client log -2 $toRevision --pretty=format:%H -- $path"), 'array');
if(isset($list[1])) $fromRevision = $list[1];
if(!isset($list[1])) return execCmd(escapeCmd("$this->client show HEAD"), 'array');
$fromRevision = $list[1];
}
$lines = execCmd(escapeCmd("$this->client diff $fromRevision $toRevision -- $path"), 'array');
return $lines;
+2 -2
View File
@@ -115,8 +115,8 @@ class Subversion
ksort($dirs);
$tags = array();
$trimmed = trim($path, '/');
$prefix = empty($trimmed) ? '/' : '/' . $trimmed . '/';
$trimed = trim($path, '/');
$prefix = empty($trimed) ? '/' : '/' . $trimed . '/';
foreach($dirs as $dirNames)
{
ksort($dirNames);
+1
View File
@@ -50,6 +50,7 @@ $config->account->actionList['edit']['icon'] = 'edit';
$config->account->actionList['edit']['text'] = $lang->edit;
$config->account->actionList['edit']['hint'] = $lang->edit;
$config->account->actionList['edit']['data-toggle'] = 'modal';
$config->account->actionList['edit']['data-size'] = 'sm';
$config->account->actionList['edit']['showText'] = true;
$config->account->actionList['edit']['url'] = array('module' => 'account', 'method' => 'edit', 'params' => 'id={id}');
+2 -2
View File
@@ -67,8 +67,8 @@ class account extends control
$this->loadModel('action')->create('account', $id, 'created');
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'reload'));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse'), 'closeModal' => true));
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'callback' => 'loadCurrentPage()', 'closeModal' => true));
}
$this->app->loadLang('serverroom');
+9 -1
View File
@@ -1 +1,9 @@
#accountCreateForm .form-row {max-width: 500px;}
#accountCreateForm .form-row {max-width: 500px;}
#mainNavbar>.container {padding-top: 8px}
#mainNavbar .nav {justify-content: left; position: relative; left: 0px; top: -4px;}
@media (min-width: 1400px){#mainNavbar .nav {left: -12px;}}
#mainNavbar {background: none;}
#mainNavbar .nav-item>a {padding-right: 0.5rem}
#mainNavbar .nav-item>.active {color: unset; font-weight: 700;}
#mainNavbar .nav-item>a.active:after {position: absolute; content: ''; border-bottom: 2px solid #2e7fff; inset: 0 6px 0 15px;}
+1 -1
View File
@@ -53,7 +53,7 @@ class accountModel extends model
/* Concatenate the conditions for the query. */
if($param)
{
$query = $this->loadModel('search')->getQuery($param);
$query = $this->loadModel('search')->getZinQuery($param);
if($query)
{
$this->session->set('accountQuery', $query->sql);
+7 -2
View File
@@ -12,12 +12,17 @@ declare(strict_types=1);
namespace zin;
featureBar(li(searchToggle()));
$queryMenuLink = createLink('account', 'browse', "browseType=bySearch&param={queryID}");
featureBar
(
set::queryMenuLinkCallback(fn($key) => str_replace('{queryID}', (string)$key, $queryMenuLink)),
li(searchToggle())
);
/* zin: Define the toolbar on main menu. */
$canCreate = hasPriv('account', 'create');
$createLink = $this->createLink('account', 'create');
$createItem = array('text' => $lang->account->create, 'url' => $createLink, 'class' => 'primary', 'icon' => 'plus', 'data-toggle' => 'modal');
$createItem = array('text' => $lang->account->create, 'url' => $createLink, 'class' => 'primary', 'icon' => 'plus', 'data-toggle' => 'modal', 'data-size' => 'sm');
$tableData = initTableData($accountList, $config->account->dtable->fieldList, $this->account);
+2
View File
@@ -14,6 +14,7 @@ $config->artifactrepo->dtable->fieldList['format']['sortType'] = true;
$config->artifactrepo->dtable->fieldList['products']['title'] = $lang->repo->product;
$config->artifactrepo->dtable->fieldList['products']['name'] = 'productNames';
$config->artifactrepo->dtable->fieldList['products']['width'] = '300';
$config->artifactrepo->dtable->fieldList['products']['hint'] = true;
$config->artifactrepo->dtable->fieldList['type']['title'] = $lang->artifactrepo->type;
$config->artifactrepo->dtable->fieldList['type']['sortType'] = true;
@@ -23,6 +24,7 @@ $config->artifactrepo->dtable->fieldList['status']['sortType'] = true;
$config->artifactrepo->dtable->fieldList['url']['title'] = $lang->artifactrepo->url;
$config->artifactrepo->dtable->fieldList['url']['width'] = '400';
$config->artifactrepo->dtable->fieldList['url']['hint'] = true;
$config->artifactrepo->dtable->fieldList['actions']['type'] = 'actions';
$config->artifactrepo->dtable->fieldList['actions']['menu'] = array('edit', 'delete');
+12 -4
View File
@@ -23,7 +23,7 @@ class artifactrepo extends control
@access public
* @return void
*/
public function browse($browseType = 'all', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 24, $pageID = 1)
public function browse($browseType = 'all', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 25, $pageID = 1)
{
/* Load pager. */
$this->app->loadClass('pager', true);
@@ -38,7 +38,7 @@ class artifactrepo extends control
$this->view->recTotal = $recTotal;
$this->view->recPerPage = $recPerPage;
$this->view->artifactRepos = $artifactRepos;
$this->view->products = $this->loadModel('product')->getPairs('', 0, '', 'all');
$this->view->products = $this->loadModel('product')->getPairs('all', 0, '', 'all');
$this->view->pageLink = $this->createLink('artifactrepo', 'browse', "browseType={$browseType}&orderBy={$orderBy}&recTotal={$recTotal}&recPerPage={$recPerPage}&pageID={$pageID}");
$this->display();
@@ -57,6 +57,7 @@ class artifactrepo extends control
{
$repo = form::data($this->config->artifactrepo->form->create)
->join('products', ',')
->add('editedBy', $this->app->user->account)
->add('createdBy', $this->app->user->account)
->add('createdDate', helper::now())
->get();
@@ -104,9 +105,14 @@ class artifactrepo extends control
$artifactRepo = $this->artifactrepo->getByID($artifactRepoID);
$products = $this->loadModel('product')->getPairs('', 0, '', 'all');
$linkedProducts = $this->loadModel('product')->getByIdList(explode(',', $artifactRepo->products));
$linkedProductPairs = array_combine(array_keys($linkedProducts), helper::arrayColumn($linkedProducts, 'name'));
$products = $products + $linkedProductPairs;
$this->view->title = $this->lang->artifactrepo->edit;
$this->view->artifactRepo = $artifactRepo;
$this->view->products = $this->loadModel('product')->getPairs('', 0, '', 'all');
$this->view->products = $products;
$this->display();
}
@@ -138,7 +144,9 @@ class artifactrepo extends control
{
$repos = $this->artifactrepo->getServerRepos($serverID);
return print(json_encode($repos));
if(!$repos['result']) return $this->send(array('result' => 'fail', 'message' => $this->lang->artifactrepo->loseConnect));
return print(json_encode($repos['data']));
}
public function ajaxUpdateArtifactRepos()
+7
View File
@@ -11,12 +11,19 @@ function getArtifactRepo(event)
{
const server = $(event.target).val();
const url = $.createLink('artifactrepo', 'ajaxGetArtifactRepos', 'serverID=' + server);
if(!server) return;
toggleLoading('#repoName', true);
$.get(url, function(response)
{
repoData = JSON.parse(response);
if(repoData.result !== undefined && repoData.result === 'fail')
{
zui.Modal.alert(repoData.message);
toggleLoading('#repoName', false);
return;
}
var repoItems = [];
for(i in repoData)
{
+8 -2
View File
@@ -1,10 +1,14 @@
<?php
$lang->artifactrepo = new stdclass();
$lang->artifactrepo->common = 'Browse artifact repo';
$lang->artifactrepo->common = 'Artifact repo';
$lang->artifactrepo->browse = 'Repo List';
$lang->artifactrepo->create = 'Add artifact repo';
$lang->artifactrepo->edit = 'Edit artifact repo';
$lang->artifactrepo->delete = 'Del artifact repo';
$lang->artifactrepo->ajaxGetArtifactRepos = 'Api: Artifact Repo List';
$lang->artifactrepo->ajaxUpdateArtifactRepos = 'Api: Update Status';
$lang->artifactrepo->name = 'Name';
$lang->artifactrepo->serverID = 'Server';
$lang->artifactrepo->repoName = 'Artifact Repo';
@@ -13,4 +17,6 @@ $lang->artifactrepo->type = 'Type';
$lang->artifactrepo->status = 'Status';
$lang->artifactrepo->url = 'Repo Address';
$lang->artifactrepo->confirmDelete = 'Are you sure you want to delete this aritfact repo?';
$lang->artifactrepo->confirmDelete = 'Are you sure you want to delete this artifact repo?';
$lang->artifactrepo->deleteError = 'The artifact repo is already associated with a build. Please cancel the association and try again';
$lang->artifactrepo->loseConnect = 'Artifact repo server not responding';
+7 -2
View File
@@ -1,10 +1,14 @@
<?php
$lang->artifactrepo = new stdclass();
$lang->artifactrepo->common = 'Browse artifact repo';
$lang->artifactrepo->common = 'Artifact repo';
$lang->artifactrepo->browse = 'Repo List';
$lang->artifactrepo->create = 'Add artifact repo';
$lang->artifactrepo->edit = 'Edit artifact repo';
$lang->artifactrepo->delete = 'Del artifact repo';
$lang->artifactrepo->ajaxGetArtifactRepos = 'Api: Artifact Repo List';
$lang->artifactrepo->ajaxUpdateArtifactRepos = 'Api: Update Status';
$lang->artifactrepo->name = 'Name';
$lang->artifactrepo->serverID = 'Server';
$lang->artifactrepo->repoName = 'Artifact Repo';
@@ -13,5 +17,6 @@ $lang->artifactrepo->type = 'Type';
$lang->artifactrepo->status = 'Status';
$lang->artifactrepo->url = 'Repo Address';
$lang->artifactrepo->confirmDelete = 'The artifact repo cannot be restored after deletion. Are you sure you want to continue?';
$lang->artifactrepo->confirmDelete = 'Are you sure you want to delete this artifact repo?';
$lang->artifactrepo->deleteError = 'The artifact repo is already associated with a build. Please cancel the association and try again';
$lang->artifactrepo->loseConnect = 'Artifact repo server not responding';
+8 -2
View File
@@ -1,10 +1,14 @@
<?php
$lang->artifactrepo = new stdclass();
$lang->artifactrepo->common = 'Browse artifact repo';
$lang->artifactrepo->common = 'Artifact repo';
$lang->artifactrepo->browse = 'Repo List';
$lang->artifactrepo->create = 'Add artifact repo';
$lang->artifactrepo->edit = 'Edit artifact repo';
$lang->artifactrepo->delete = 'Del artifact repo';
$lang->artifactrepo->ajaxGetArtifactRepos = 'Api: Artifact Repo List';
$lang->artifactrepo->ajaxUpdateArtifactRepos = 'Api: Update Status';
$lang->artifactrepo->name = 'Name';
$lang->artifactrepo->serverID = 'Server';
$lang->artifactrepo->repoName = 'Artifact Repo';
@@ -13,4 +17,6 @@ $lang->artifactrepo->type = 'Type';
$lang->artifactrepo->status = 'Status';
$lang->artifactrepo->url = 'Repo Address';
$lang->artifactrepo->confirmDelete = 'Are you sure you want to delete this aritfact repo?';
$lang->artifactrepo->confirmDelete = 'Are you sure you want to delete this artifact repo?';
$lang->artifactrepo->deleteError = 'The artifact repo is already associated with a build. Please cancel the association and try again';
$lang->artifactrepo->loseConnect = 'Artifact repo server not responding';
+7 -2
View File
@@ -1,10 +1,14 @@
<?php
$lang->artifactrepo = new stdclass();
$lang->artifactrepo->common = '浏览制品库';
$lang->artifactrepo->common = '制品库';
$lang->artifactrepo->browse = '制品库列表';
$lang->artifactrepo->create = '添加制品库';
$lang->artifactrepo->edit = '编辑制品库';
$lang->artifactrepo->delete = '删除制品库';
$lang->artifactrepo->ajaxGetArtifactRepos = '接口:制品库列表';
$lang->artifactrepo->ajaxUpdateArtifactRepos = '接口:更新制品库状态';
$lang->artifactrepo->name = '名称';
$lang->artifactrepo->serverID = '服务器';
$lang->artifactrepo->repoName = '制品库';
@@ -13,5 +17,6 @@ $lang->artifactrepo->type = '类型';
$lang->artifactrepo->status = '状态';
$lang->artifactrepo->url = '库地址';
$lang->artifactrepo->confirmDelete = '制品库删除后无法还原,你确认要继续么?';
$lang->artifactrepo->confirmDelete = '您确认要删除该制品库吗?';
$lang->artifactrepo->deleteError = '当前制品库中制品已关联版本,请取消关联后重试。';
$lang->artifactrepo->loseConnect = '制品库服务器无法连接';
+4 -4
View File
@@ -71,12 +71,12 @@ class artifactrepoModel extends model
if($server->type == 'nexus')
{
$url = $server->url . '/service/rest/v1/repositorySettings';
$url = $server->url . '/service/rest/v1/repositorySettings';
$auth = "{$server->account}:{$server->password}";
$response = common::http($url, '', array(CURLOPT_USERPWD => $auth));
$data = json_decode($response);
return is_array($data) ? $data : array();
$response = common::http($url, '', array(CURLOPT_USERPWD => $auth), array(), 'data', 'POST', 10, true);
$data = array('result' => $response[1] == 200, 'data' => json_decode($response['body']));
return $data;
}
return array();
+2 -1
View File
@@ -26,8 +26,9 @@ foreach($artifactRepos as $repo)
foreach($productList as $productID)
{
if(!isset($products[$productID])) continue;
$repo->productNames .= ' ' . zget($products, $productID, $productID);
$repo->productNames .= ',' . zget($products, $productID, $productID);
}
$repo->productNames = trim($repo->productNames, ',');
}
}
$artifactRepos = initTableData($artifactRepos, $config->artifactrepo->dtable->fieldList, $this->artifactrepo);
+3
View File
@@ -13,6 +13,7 @@ namespace zin;
formPanel
(
set::title($lang->artifactrepo->create),
set::actionsClass('w-2/3'),
formGroup
(
set::width('2/3'),
@@ -50,6 +51,7 @@ formPanel
(
set::width('2/3'),
set::name('type'),
set::required(true),
set::label($lang->artifactrepo->type),
set::readonly(true),
input
@@ -62,6 +64,7 @@ formPanel
(
set::width('2/3'),
set::name('status'),
set::required(true),
set::label($lang->artifactrepo->status),
set::readonly(true),
),
+1
View File
@@ -13,6 +13,7 @@ namespace zin;
formPanel
(
set::title($lang->artifactrepo->edit),
set::actionsClass('w-2/3'),
formGroup
(
set::width('2/3'),
+28
View File
@@ -0,0 +1,28 @@
<?php
$lang->CNE->InstallSuccess = 'Install Success';
$lang->CNE->InstallFailure = 'Install Fail';
$lang->CNE->serverError = 'CNE Server Error';
$lang->CNE->statusList = array();
$lang->CNE->statusList['normal'] = 'Normal';
$lang->CNE->statusList['abnormal'] = 'Abnormal';
$lang->CNE->statusList['stopped'] = 'Stopped';
$lang->CNE->statusList['unknown'] = 'UnKnown';
$lang->CNE->statusIcons = array();
$lang->CNE->statusIcons['normal'] = "check";
$lang->CNE->statusIcons['abnormal'] = "exclamation-pure";
$lang->CNE->statusIcons['stopped'] = "pause-pure";
$lang->CNE->statusIcons['unknown'] = "exclamation-pure";
$lang->CNE->errorList = array();
//$lang->CNE->errorList[400] = '不能包含特殊字符';
$lang->CNE->errorList[400] = 'Request api fail';
$lang->CNE->errorList[404] = 'Service no exist';
$lang->CNE->errorList[40004] = 'Certificate does not match the domain';
$lang->CNE->errorList[41001] = 'Certificate expired';
$lang->CNE->errorList[41002] = 'Certificate mismatch';
$lang->CNE->errorList[41003] = 'Incomplete certificate chain';
$lang->CNE->errorList[41004] = 'Private key does not match the certificate';
$lang->CNE->errorList[41005] = 'Certificate parsing failed';
$lang->CNE->errorList[41006] = 'Key parsing failed';
+15 -15
View File
@@ -1,28 +1,28 @@
<?php
$lang->CNE->InstallSuccess = 'Installation Succeeded';
$lang->CNE->InstallFailure = 'Installation Failed';
$lang->CNE->InstallSuccess = 'Install Success';
$lang->CNE->InstallFailure = 'Install Fail';
$lang->CNE->serverError = 'CNE Server Error';
$lang->CNE->statusList = array();
$lang->CNE->statusList['normal'] = 'Normal';
$lang->CNE->statusList['abnormal'] = 'Anomaly';
$lang->CNE->statusList['abnormal'] = 'Abnormal';
$lang->CNE->statusList['stopped'] = 'Stopped';
$lang->CNE->statusList['unknown'] = 'Unknown';
$lang->CNE->statusList['unknown'] = 'UnKnown';
$lang->CNE->statusIcons = array();
$lang->CNE->statusIcons['normal'] = "<i class='icon icon-5x icon-check-circle status-green'></i>";
$lang->CNE->statusIcons['abnormal'] = "<i class='icon icon-5x icon-close-circle status-red'></i>";
$lang->CNE->statusIcons['stopped'] = "<i class='icon icon-5x icon-off status-gray'></i>";
$lang->CNE->statusIcons['unknown'] = "<i class='icon icon-5x icon-alert-sign status-orange'></i>";
$lang->CNE->statusIcons['normal'] = "check";
$lang->CNE->statusIcons['abnormal'] = "exclamation-pure";
$lang->CNE->statusIcons['stopped'] = "pause-pure";
$lang->CNE->statusIcons['unknown'] = "exclamation-pure";
$lang->CNE->errorList = array();
//$lang->CNE->errorList[400] = 'Only number and letter allowed';
$lang->CNE->errorList[400] = 'Failed to request cluster info';
$lang->CNE->errorList[404] = 'Service does not exist';
//$lang->CNE->errorList[400] = '不能包含特殊字符';
$lang->CNE->errorList[400] = 'Request api fail';
$lang->CNE->errorList[404] = 'Service no exist';
$lang->CNE->errorList[40004] = 'Certificate does not match the domain';
$lang->CNE->errorList[41001] = 'Certificate has expired';
$lang->CNE->errorList[41001] = 'Certificate expired';
$lang->CNE->errorList[41002] = 'Certificate mismatch';
$lang->CNE->errorList[41003] = 'Incomplete certificate chain';
$lang->CNE->errorList[41004] = 'Certificate and private key do not match';
$lang->CNE->errorList[41005] = 'Failed parsing certificate';
$lang->CNE->errorList[41006] = 'Failed parsing key';
$lang->CNE->errorList[41004] = 'Private key does not match the certificate';
$lang->CNE->errorList[41005] = 'Certificate parsing failed';
$lang->CNE->errorList[41006] = 'Key parsing failed';
+28
View File
@@ -0,0 +1,28 @@
<?php
$lang->CNE->InstallSuccess = 'Install Success';
$lang->CNE->InstallFailure = 'Install Fail';
$lang->CNE->serverError = 'CNE Server Error';
$lang->CNE->statusList = array();
$lang->CNE->statusList['normal'] = 'Normal';
$lang->CNE->statusList['abnormal'] = 'Abnormal';
$lang->CNE->statusList['stopped'] = 'Stopped';
$lang->CNE->statusList['unknown'] = 'UnKnown';
$lang->CNE->statusIcons = array();
$lang->CNE->statusIcons['normal'] = "check";
$lang->CNE->statusIcons['abnormal'] = "exclamation-pure";
$lang->CNE->statusIcons['stopped'] = "pause-pure";
$lang->CNE->statusIcons['unknown'] = "exclamation-pure";
$lang->CNE->errorList = array();
//$lang->CNE->errorList[400] = '不能包含特殊字符';
$lang->CNE->errorList[400] = 'Request api fail';
$lang->CNE->errorList[404] = 'Service no exist';
$lang->CNE->errorList[40004] = 'Certificate does not match the domain';
$lang->CNE->errorList[41001] = 'Certificate expired';
$lang->CNE->errorList[41002] = 'Certificate mismatch';
$lang->CNE->errorList[41003] = 'Incomplete certificate chain';
$lang->CNE->errorList[41004] = 'Private key does not match the certificate';
$lang->CNE->errorList[41005] = 'Certificate parsing failed';
$lang->CNE->errorList[41006] = 'Key parsing failed';
+28
View File
@@ -0,0 +1,28 @@
<?php
$lang->CNE->InstallSuccess = 'Install Success';
$lang->CNE->InstallFailure = 'Install Fail';
$lang->CNE->serverError = 'CNE Server Error';
$lang->CNE->statusList = array();
$lang->CNE->statusList['normal'] = 'Normal';
$lang->CNE->statusList['abnormal'] = 'Abnormal';
$lang->CNE->statusList['stopped'] = 'Stopped';
$lang->CNE->statusList['unknown'] = 'UnKnown';
$lang->CNE->statusIcons = array();
$lang->CNE->statusIcons['normal'] = "check";
$lang->CNE->statusIcons['abnormal'] = "exclamation-pure";
$lang->CNE->statusIcons['stopped'] = "pause-pure";
$lang->CNE->statusIcons['unknown'] = "exclamation-pure";
$lang->CNE->errorList = array();
//$lang->CNE->errorList[400] = '不能包含特殊字符';
$lang->CNE->errorList[400] = 'Request api fail';
$lang->CNE->errorList[404] = 'Service no exist';
$lang->CNE->errorList[40004] = 'Certificate does not match the domain';
$lang->CNE->errorList[41001] = 'Certificate expired';
$lang->CNE->errorList[41002] = 'Certificate mismatch';
$lang->CNE->errorList[41003] = 'Incomplete certificate chain';
$lang->CNE->errorList[41004] = 'Private key does not match the certificate';
$lang->CNE->errorList[41005] = 'Certificate parsing failed';
$lang->CNE->errorList[41006] = 'Key parsing failed';
+4 -4
View File
@@ -10,10 +10,10 @@ $lang->CNE->statusList['stopped'] = '关闭';
$lang->CNE->statusList['unknown'] = '无数据';
$lang->CNE->statusIcons = array();
$lang->CNE->statusIcons['normal'] = "<i class='icon icon-5x icon-check-circle status-green'></i>";
$lang->CNE->statusIcons['abnormal'] = "<i class='icon icon-5x icon-close-circle status-red'></i>";
$lang->CNE->statusIcons['stopped'] = "<i class='icon icon-5x icon-off status-gray'></i>";
$lang->CNE->statusIcons['unknown'] = "<i class='icon icon-5x icon-alert-sign status-orange'></i>";
$lang->CNE->statusIcons['normal'] = "check";
$lang->CNE->statusIcons['abnormal'] = "exclamation-pure";
$lang->CNE->statusIcons['stopped'] = "pause-pure";
$lang->CNE->statusIcons['unknown'] = "exclamation-pure";
$lang->CNE->errorList = array();
//$lang->CNE->errorList[400] = '不能包含特殊字符';
+28
View File
@@ -0,0 +1,28 @@
<?php
$lang->CNE->InstallSuccess = '安装成功';
$lang->CNE->InstallFailure = '安装失败';
$lang->CNE->serverError = 'CNE服务器出错';
$lang->CNE->statusList = array();
$lang->CNE->statusList['normal'] = '正常';
$lang->CNE->statusList['abnormal'] = '异常';
$lang->CNE->statusList['stopped'] = '关闭';
$lang->CNE->statusList['unknown'] = '无数据';
$lang->CNE->statusIcons = array();
$lang->CNE->statusIcons['normal'] = "check";
$lang->CNE->statusIcons['abnormal'] = "exclamation-pure";
$lang->CNE->statusIcons['stopped'] = "pause-pure";
$lang->CNE->statusIcons['unknown'] = "exclamation-pure";
$lang->CNE->errorList = array();
//$lang->CNE->errorList[400] = '不能包含特殊字符';
$lang->CNE->errorList[400] = '请求集群接口失败';
$lang->CNE->errorList[404] = '服务不存在';
$lang->CNE->errorList[40004] = '证书与域名不匹配';
$lang->CNE->errorList[41001] = '证书过期';
$lang->CNE->errorList[41002] = '证书不匹配';
$lang->CNE->errorList[41003] = '证书链不完整';
$lang->CNE->errorList[41004] = '私钥与证书不匹配';
$lang->CNE->errorList[41005] = '证书解析失败';
$lang->CNE->errorList[41006] = '密钥解析失败';
+43 -17
View File
@@ -50,7 +50,7 @@ class cneModel extends model
if(empty($result) || $result->code != 200 || empty($result->data)) return array();
$instanceList = $result->data;
return array_combine(array_column($instanceList, 'name'), $instanceList);
return array_combine(helper::arrayColumn($instanceList, 'name'), $instanceList);
}
/**
@@ -335,7 +335,7 @@ class cneModel extends model
$customDomain = $this->loadModel('setting')->getItem('owner=system&module=common&section=domain&key=customDomain');
if($customDomain) return $customDomain;
return getenv('APP_DOMAIN') ? getenv('APP_DOMAIN') : $this->config->CNE->app->domain;
return getenv('APP_DOMAIN');
}
/**
@@ -449,7 +449,7 @@ class cneModel extends model
$apiUrl = "/api/cne/statistics/app";
$result = $this->apiPost($apiUrl, $apiData, $this->config->CNE->api->headers);
if(!isset($result->code) || $result->code != 200)return array_combine(array_column($instancesMetrics, 'id'), $instancesMetrics);
if(!isset($result->code) || $result->code != 200)return array_combine(helper::arrayColumn($instancesMetrics, 'id'), $instancesMetrics);
foreach($result->data as $k8sMetric)
{
@@ -468,7 +468,7 @@ class cneModel extends model
$instancesMetrics[$k8sMetric->name]->memory->rate = $instancesMetrics[$k8sMetric->name]->memory->limit > 0 ? round($instancesMetrics[$k8sMetric->name]->memory->usage / $instancesMetrics[$k8sMetric->name]->memory->limit * 100, 2) : 0;
}
return array_combine(array_column($instancesMetrics, 'id'), $instancesMetrics);
return array_combine(helper::arrayColumn($instancesMetrics, 'id'), $instancesMetrics);
}
/**
@@ -839,22 +839,27 @@ class cneModel extends model
{
if(empty($mappings)) $mappings = array(
array(
"key" => "admin_username",
"key" => "admin_username",
"type" => "helm",
"path" => "auth.username"
),
array(
"key" => "admin_password",
"type" => "helm",
"path" => "auth.password"
"key" => "z_username",
"path" => "z_username",
"type" => "secret"
),
array(
"key" => "admin_token",
"type" => "secret",
"path" => "api_token"
"key" => "z_password",
"path" => "z_password",
"type" => "secret"
),
array(
"key" => "api_token",
"path" => "api_token",
"type" => "secret"
)
);
$apiParams = new stdclass;
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
@@ -993,7 +998,7 @@ class cneModel extends model
if(empty($result) || $result->code != 200 || empty($result->data)) return array();
$dbList = $result->data;
return array_combine(array_column($dbList, 'name'), $dbList);
return array_combine(helper::arrayColumn($dbList, 'name'), $dbList);
}
/**
@@ -1057,7 +1062,7 @@ class cneModel extends model
if(empty($result) || $result->code != 200 || empty($result->data)) return array();
$dbList = $result->data;
return array_combine(array_column($dbList, 'name'), $dbList);
return array_combine(helper::arrayColumn($dbList, 'name'), $dbList);
}
/**
@@ -1077,7 +1082,7 @@ class cneModel extends model
if(empty($result) || $result->code != 200 || empty($result->data)) return array();
$dbList = $result->data;
return array_combine(array_column($dbList, 'name'), $dbList);
return array_combine(helper::arrayColumn($dbList, 'name'), $dbList);
}
/**
@@ -1144,8 +1149,12 @@ class cneModel extends model
public function apiPost($url, $data, $header = array(), $host = '')
{
$requestUri = ($host ? $host : $this->config->CNE->api->host) . $url;
$result = json_decode(commonModel::http($requestUri, $data, array(CURLOPT_CUSTOMREQUEST => 'POST'), $header, 'json', 20));
if($result && $result->code == 200) return $result;
$result = json_decode(commonModel::http($requestUri, $data, array(CURLOPT_CUSTOMREQUEST => 'POST'), $header, 'json', 'POST', 20));
if($result && in_array($result->code, array(200, 201)))
{
$result->code = 200;
return $result;
}
if($result) return $this->translateError($result);
return $this->cneServerError();
@@ -1313,4 +1322,21 @@ class cneModel extends model
$apiUrl = "/api/cne/platform/restore/status";
return $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* app资源调度尝试。
* Try allocate for apps.
*
* @param array $apps
* @access public
* @return object
*/
public function tryAllocate(array $resources): object
{
$apiParams = new stdclass();
$apiParams->requests = $resources;
$apiUrl = "/api/cne/system/resource/try-allocate";
return $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
}
+10 -2
View File
@@ -69,6 +69,8 @@ class gitModel extends model
/* Get repos and load module. */
$this->setRepos();
$this->loadModel('job');
$this->loadModel('gitlab');
$this->loadModel('repo');
if(empty($this->repos)) return false;
@@ -82,7 +84,11 @@ class gitModel extends model
{
$this->updateCommit($repo, $commentGroup, true);
if($repo->SCM == 'Gitlab') $this->loadModel('gitlab')->updateCodePath((int)$repo->serviceHost, (int)$repo->serviceProject, (int)$repo->id);
if($repo->SCM == 'Gitlab')
{
$this->gitlab->updateCodePath((int)$repo->serviceHost, (int)$repo->serviceProject, (int)$repo->id);
$this->repo->updateCommitDate((int)$repo->id);
}
/* Create compile by tag. */
$jobs = zget($tagGroup, $repoID, array());
@@ -120,6 +126,8 @@ class gitModel extends model
*/
public function updateCommit($repo, $commentGroup, $printLog = true)
{
if($repo->SCM == 'Gitlab') return;
/* Load module and print log. */
$this->loadModel('repo');
if($printLog) $this->printLog("begin repo $repo->id");
@@ -202,7 +210,7 @@ class gitModel extends model
if(empty($objectIDs) or !isset($objectTypeMap[$objectType])) continue;
$this->post->$objectType = $objectIDs;
$this->repo->link($repo->id, $log->revision, $objectTypeMap[$objectType]);
$this->repo->link($repo->id, $log->revision, $objectTypeMap[$objectType], 'commit');
}
}
}
+15 -9
View File
@@ -20,6 +20,8 @@ class gitea extends control
{
parent::__construct($moduleName, $methodName);
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
/* This is essential when changing tab(menu) from gitea to repo. */
/* Optional: common::setMenuVars('devops', $this->session->repoID); */
if($this->app->rawMethod != 'binduser') $this->loadModel('ci')->setMenu();
@@ -163,8 +165,9 @@ class gitea extends control
$changes = common::createChanges($oldGitea, $gitea);
$this->loadModel('action')->logHistory($actionID, $changes);
$response['load'] = true;
$response['result'] = 'success';
$response['load'] = $this->createLink('space', 'browse');
$response['message'] = zget($this->lang->instance->notices, 'uninstallSuccess');
$response['result'] = 'success';
return $this->send($response);
}
@@ -196,7 +199,7 @@ class gitea extends control
* @access public
* @return void
*/
public function bindUser(int $giteaID, string $type = 'all')
public function bindUser($giteaID, $type = 'all')
{
$zentaoUsers = $this->dao->select('account,email,realname')->from(TABLE_USER)->fetchAll('account');
$userPairs = $this->loadModel('user')->getPairs('noclosed|noletter');
@@ -204,12 +207,12 @@ class gitea extends control
if($_POST)
{
$this->gitea->bindUser($giteaID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->server->http_referer));
if(dao::isError()) return $this->sendError(dao::getError());
return $this->sendSuccess(array('message' => $this->lang->saveSuccess, 'load' => helper::createLink('space', 'browse')));
}
$userList = array();
$giteaUsers = $this->gitea->apiGetUsers($giteaID);
$giteaUsers = $this->gitea->apiGetUsers($giteaID);
$bindedUsers = $this->gitea->getUserAccountIdPairs($giteaID);
$matchedResult = $this->gitea->getMatchedUsers($giteaID, $giteaUsers, $zentaoUsers);
@@ -245,6 +248,7 @@ class gitea extends control
$this->view->recTotal = count($userList);
$this->view->userList = $userList;
$this->view->userPairs = $userPairs;
$this->view->zentaoUsers = $zentaoUsers;
$this->display();
}
@@ -263,11 +267,13 @@ class gitea extends control
$project = urldecode(base64_decode($project));
$branches = $this->gitea->apiGetBranches($giteaID, $project);
$options = "<option value=''></option>";
$options = array();
$options[] = array('text' => '', 'value' => '');;
foreach($branches as $branch)
{
$options .= "<option value='{$branch->name}'>{$branch->name}</option>";
$options[] = array('text' => $branch->name, 'value' => $branch->name);
}
$this->send($options);
return print(json_encode($options));
}
}
+24
View File
@@ -0,0 +1,24 @@
$(document).ready(function()
{
$('.gitlab-user-bind').change(function()
{
var user = zentaoUsers[$(this).val()];
if(user !== undefined)
{
$(this).parent().parent().find('.email').text(user.email)
}
});
$(document).on('click', '.zentao-users .chosen-container', function()
{
var $obj = $(this).prev('select');
var value = $obj.val();
if($obj.hasClass('filled')) return false;
$obj.empty();
$obj.append($('#userList').html());
$obj.val(value);
$obj.addClass('filled');
$obj.trigger("chosen:updated");
})
});
+21 -1
View File
@@ -10,7 +10,27 @@ window.setUserEmail = function()
window.renderGitlabUser = function(result, {row})
{
const giteaID = row.data.giteaID;
result.push({html: `<input type="hidden" name='giteaUserNames[]' value='${giteaID}'>`});
result.push({html: '<input type="hidden" name="giteaUserNames[' + row.id + ']" value="' + giteaID + '">'});
return result;
}
window.bindUser = function()
{
const myDTable = $('#table-gitea-binduser').zui('dtable');
const formData = myDTable.$.getFormData();
var bindData = $('#table-gitea-binduser').zui('dtable').$.props.data;
var postData = {};
postData['giteaUserNames[]'] = [];
for(i in bindData)
{
postData['giteaUserNames[]'].push(bindData[i].giteaID);
postData['zentaoUsers[' + bindData[i].giteaID + ']'] = formData['zentaoUsers[' + bindData[i].giteaID + ']'];
}
$.ajaxSubmit({
url: $.createLink('gitea', 'bindUser', 'giteaID=' + giteaID + '&type=' + type),
data: postData
});
}
+1
View File
@@ -13,6 +13,7 @@ $lang->gitea->giteaAccount = 'Gitea Account';
$lang->gitea->giteaEmail = 'Email';
$lang->gitea->zentaoAccount = 'Zentao Account';
$lang->gitea->bindingStatus = 'Binding Status';
$lang->gitea->all = 'All';
$lang->gitea->notBind = 'Not bind';
$lang->gitea->binded = 'Binded';
$lang->gitea->bindDynamic = '%s and Zentao user %s';
+1
View File
@@ -13,6 +13,7 @@ $lang->gitea->giteaAccount = 'Gitea Account';
$lang->gitea->giteaEmail = 'Email';
$lang->gitea->zentaoAccount = 'Zentao Account';
$lang->gitea->bindingStatus = 'Binding Status';
$lang->gitea->all = 'All';
$lang->gitea->notBind = 'Not bind';
$lang->gitea->binded = 'Binded';
$lang->gitea->bindDynamic = '%s and Zentao user %s';
+1
View File
@@ -13,6 +13,7 @@ $lang->gitea->giteaAccount = 'Gitea Account';
$lang->gitea->giteaEmail = 'Email';
$lang->gitea->zentaoAccount = 'Zentao Account';
$lang->gitea->bindingStatus = 'Binding Status';
$lang->gitea->all = 'All';
$lang->gitea->notBind = 'Not bind';
$lang->gitea->binded = 'Binded';
$lang->gitea->bindDynamic = '%s and Zentao user %s';
+1
View File
@@ -13,6 +13,7 @@ $lang->gitea->giteaAccount = 'Gitea用户';
$lang->gitea->giteaEmail = '邮箱';
$lang->gitea->zentaoAccount = '禅道用户';
$lang->gitea->bindingStatus = '绑定状态';
$lang->gitea->all = '全部';
$lang->gitea->notBind = '未绑定';
$lang->gitea->binded = '已绑定';
$lang->gitea->bindDynamic = '%s与禅道用户%s';
+10 -11
View File
@@ -98,9 +98,9 @@ class giteaModel extends model
*
* @param int $giteaID
* @access public
* @return bool
* @return array
*/
public function bindUser(int $giteaID): bool
public function bindUser($giteaID)
{
$userPairs = $this->loadModel('user')->getPairs('noclosed|noletter');
$users = $this->post->zentaoUsers;
@@ -116,7 +116,7 @@ class giteaModel extends model
if(count($repeatUsers))
{
dao::$errors[] = sprintf($this->lang->gitea->bindUserError, join(',', $repeatUsers));
dao::$errors = sprintf($this->lang->gitea->bindUserError, join(',', $repeatUsers));
return false;
}
@@ -148,8 +148,6 @@ class giteaModel extends model
$this->loadModel('action')->create('giteauser', $giteaID, 'bind', '', sprintf($this->lang->gitea->bindDynamic, $giteaNames[$openID], $zentaoUsers[$account]->realname));
}
}
return true;
}
/**
@@ -308,13 +306,13 @@ class giteaModel extends model
/**
* Get matched gitea users.
*
* @param int $giteaID
* @param array $giteaUsers
* @param array $zentaoUsers
* @param int $giteaID
* @param array $giteaUsers
* @param array $zentaoUsers
* @access public
* @return array
*/
public function getMatchedUsers(int $giteaID, array $giteaUsers, array $zentaoUsers): array
public function getMatchedUsers($giteaID, $giteaUsers, $zentaoUsers)
{
$matches = new stdclass;
foreach($giteaUsers as $giteaUser)
@@ -331,9 +329,9 @@ class giteaModel extends model
$matchedUsers = array();
foreach($giteaUsers as $giteaUser)
{
if(isset($bindedUsers[$giteaUser->account]))
if(isset($bindedUsers[$giteaUser->id]))
{
$giteaUser->zentaoAccount = $bindedUsers[$giteaUser->account];
$giteaUser->zentaoAccount = $bindedUsers[$giteaUser->id];
$matchedUsers[$giteaUser->id] = $giteaUser;
continue;
}
@@ -379,6 +377,7 @@ class giteaModel extends model
$gitea = $this->getByID($giteaID);
$oauth = "oauth2:{$gitea->token}@";
$project->tokenCloneUrl = preg_replace('/(http(s)?:\/\/)/', "\$1$oauth", $project->html_url);
$project->tokenCloneUrl = str_replace(array('https://', 'http://'), strstr($url, ':', true) . '://', $project->tokenCloneUrl);
}
return $project;
+3 -1
View File
@@ -24,6 +24,8 @@ featureBar
toolbar();
jsVar('zentaoUsers', $zentaoUsers);
jsVar('giteaID', $giteaID);
jsVar('type', $type);
$config->gitea->dtable->bindUser->fieldList['giteaEmail']['onRenderCell'] = jsRaw('renderGitlabUser');
$config->gitea->dtable->bindUser->fieldList['zentaoUsers']['controlItems'] = $userPairs;
form
@@ -48,7 +50,7 @@ form
array(
'text' => $lang->save,
'btnType' => 'primary',
'onClick' => jsRaw("() => {\$('#bindForm').trigger('submit')}")
'onClick' => jsRaw("() => {bindUser()}")
),
array(
'text' => $lang->goback,
+48 -34
View File
@@ -11,60 +11,66 @@
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php $browseLink = $this->createLink('gitea', 'browse', ""); ?>
<?php js::set('zentaoUsers', $zentaoUsers);?>
<div id="mainContent" class="main-content">
<div class="main-header">
<h2><?php echo $lang->gitea->bindUser;?></h2>
<div class="main-header gitea-bind">
<?php
echo html::linkButton('<i class="icon icon-back icon-sm"></i> ' . $lang->goback, $browseLink, 'self', "data-app='{$app->tab}'", 'btn btn-secondary');
$allLink = $this->createLink('gitea', 'binduser', "giteaID={$giteaID}&type=all");
$bindedLink = $this->createLink('gitea', 'binduser', "giteaID={$giteaID}&type=binded");
$notBindLink = $this->createLink('gitea', 'binduser', "giteaID={$giteaID}&type=notBind");
if($type == 'all')
{
echo html::linkButton('' . $lang->gitea->all . "<span class='gitea-bind-all'>" . count($giteaUsers) . "</span>", $allLink, 'self', "data-app='{$app->tab}'", 'btn btn-info active');
echo html::linkButton('' . $lang->gitea->notBind, $notBindLink, 'self', "data-app='{$app->tab}'", 'btn btn-info');
echo html::linkButton('' . $lang->gitea->binded, $bindedLink, 'self', "data-app='{$app->tab}'", 'btn btn-info');
}
else if($type == 'binded')
{
echo html::linkButton('' . $lang->gitea->all, $allLink, 'self', "data-app='{$app->tab}'", 'btn btn-info');
echo html::linkButton('' . $lang->gitea->notBind, $notBindLink, 'self', "data-app='{$app->tab}'", 'btn btn-info');
echo html::linkButton('' . $lang->gitea->binded . "<span class='gitea-bind-all'>" . count($giteaUsers) . "</span>", $bindedLink, 'self', "data-app='{$app->tab}'", 'btn btn-info active');
}
else
{
echo html::linkButton('' . $lang->gitea->all, $allLink, 'self', "data-app='{$app->tab}'", 'btn btn-info');
echo html::linkButton('' . $lang->gitea->notBind . "<span class='gitea-bind-all'>" . count($giteaUsers) . "</span>", $notBindLink, 'self', "data-app='{$app->tab}'", 'btn btn-info active');
echo html::linkButton('' . $lang->gitea->binded, $bindedLink, 'self', "data-app='{$app->tab}'", 'btn btn-info');
}
?>
</div>
<form method='post' class='load-indicator main-form form-ajax' enctype='multipart/form-data'>
<div class="table-responsive">
<table class="table table-borderless w-800px">
<table class="table table-borderless">
<thead>
<tr>
<th class='w-60px'><?php echo $lang->gitea->giteaAvatar;?></th>
<th><?php echo $lang->gitea->giteaAccount;?></th>
<th><?php echo $lang->gitea->giteaEmail;?></th>
<th class='w-150px'><?php echo $lang->gitea->zentaoAccount;?></th>
<th><?php echo $lang->gitea->zentaoEmail;?></th>
<th class="w-400px"><?php echo $lang->gitea->zentaoAccount;?> <span class="gitea-account-desc"><?php echo $lang->gitea->accountDesc;?></span></th>
<th><?php echo $lang->gitea->bindingStatus;?></th>
</tr>
</thead>
<tbody>
<?php foreach($giteaUsers as $giteaUser):?>
<?php if(isset($giteaUser->zentaoAccount)) continue;?>
<?php echo html::hidden("giteaUserNames[$giteaUser->account]", $giteaUser->realname);?>
<?php echo html::hidden("giteaUserNames[$giteaUser->id]", $giteaUser->realname);?>
<tr>
<td><?php echo html::image($giteaUser->avatar, "height=40");?></td>
<td class='text-left'>
<strong><?php echo $giteaUser->realname;?></strong>
<br>
<?php echo $giteaUser->account;?>
<td>
<?php echo html::image($giteaUser->avatar, "height=20 width=20 class='img-circle'");?>
<?php echo $giteaUser->realname . '@' . $giteaUser->account;?>
</td>
<td><?php echo $giteaUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$giteaUser->account]", $userPairs, '', "class='form-control select chosen'" );?></td>
<td><?php echo $lang->gitea->notBind;?></td>
</tr>
<?php endforeach;?>
<?php foreach($giteaUsers as $giteaUser):?>
<?php if(!isset($giteaUser->zentaoAccount)) continue;?>
<?php echo html::hidden("giteaUserNames[$giteaUser->account]", $giteaUser->realname);?>
<tr>
<td><?php echo html::image($giteaUser->avatar, "height=40");?></td>
<td class="email"><?php echo !empty($giteaUser->zentaoAccount) ? $zentaoUsers[$giteaUser->zentaoAccount]->email : '';?></td>
<td class='zentao-users'><?php echo html::select("zentaoUsers[$giteaUser->id]", $giteaUser->zentaoUsers, $giteaUser->zentaoAccount, "class='form-control select chosen gitea-user-bind'" );?></td>
<td>
<strong><?php echo $giteaUser->realname;?></strong>
<br>
<?php echo $giteaUser->account;?>
</td>
<td><?php echo $giteaUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$giteaUser->account]", $userPairs, $giteaUser->zentaoAccount, "class='form-control select chosen'" );?></td>
<td>
<?php if(isset($bindedUsers[$giteaUser->zentaoAccount])):?>
<?php $zentaoAccount = zget($userPairs, $giteaUser->zentaoAccount, '');?>
<?php if(!empty($zentaoAccount)):?>
<?php if($giteaUser->binded === 1):?>
<?php echo $lang->gitea->binded;?>
<?php else:?>
<?php elseif($giteaUser->binded === 2):?>
<?php echo '<span class="text-red">' . $lang->gitea->bindedError . '</span>';?>
<?php endif;?>
<?php else:?>
<?php echo $lang->gitea->notBind;?>
<?php echo '<span class="text-red">' . $lang->gitea->notBind . '</span>';?>
<?php endif;?>
</td>
</tr>
@@ -82,4 +88,12 @@
</div>
</form>
</div>
<div id="userList" class="hidden">
<?php
foreach($userPairs as $account => $realname)
{
echo "<option value='$account' title='$realname'>$realname</option>";
}
?>
</div>
<?php include '../../common/view/footer.html.php';?>
+21 -4
View File
@@ -20,6 +20,15 @@ class gitlab extends control
{
parent::__construct($moduleName, $methodName);
if(stripos($this->methodName, 'ajax') === false)
{
if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
if(!in_array(strtolower(strtolower($this->methodName)), array('browseproject', 'browsegroup', 'browseuser', 'browsebranch', 'browsetag')))
{
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
}
}
/* This is essential when changing tab(menu) from gitlab to repo. */
/* Optional: common::setMenuVars('devops', $this->session->repoID); */
$this->loadModel('ci')->setMenu();
@@ -195,7 +204,9 @@ class gitlab extends control
$this->loadModel('action')->create('gitlabuser', $openID, 'bind', '', sprintf($this->lang->gitlab->bindDynamic, $gitlabNames[$openID], $zentaoUsers[$account]->realname));
}
}
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('gitlab', 'browse')));
if(dao::isError()) return $this->sendError(dao::getError());
return $this->sendSuccess(array('message' => $this->lang->saveSuccess, 'load' => helper::createLink('space', 'browse')));
}
$userList = array();
@@ -263,7 +274,7 @@ class gitlab extends control
$changes = common::createChanges($oldGitLab, $gitLab);
$this->loadModel('action')->logHistory($actionID, $changes);
$response['load'] = true;
$response['load'] = $this->createLink('space', 'browse');
$response['result'] = 'success';
return $this->send($response);
}
@@ -618,7 +629,12 @@ class gitlab extends control
{
$this->gitlab->createUser($gitlabID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
if(dao::isError())
{
$message = dao::getError();
foreach($message as &$msg) if(is_string($msg)) $msg = zget($this->lang->gitlab->errorResonse, $msg, $msg);
return $this->send(array('result' => 'fail', 'message' => $message));
}
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browseUser', "gitlabID=$gitlabID")));
}
@@ -725,7 +741,7 @@ class gitlab extends control
if(!$this->app->user->admin)
{
$openID = $this->gitlab->getUserIDByZentaoAccount($gitlabID, $this->app->user->account);
if(!$openID) return print(js::alert($this->lang->gitlab->mustBindUser) . js::locate($this->createLink('gitlab', 'browse')));
if(!$openID) return print(js::alert($this->lang->gitlab->mustBindUser) . js::locate($this->createLink('space', 'browse')));
}
$this->app->loadClass('pager', true);
@@ -745,6 +761,7 @@ class gitlab extends control
if(!$project->adminer and isset($project->owner) and $project->owner->id == $openID) $project->adminer = true;
$project->isMaintainer = $this->gitlab->checkUserAccess($gitlabID, $project->id, $project, $groupIDList, 'maintainer');
$project->isDeveloper = $this->gitlab->checkUserAccess($gitlabID, $project->id, $project, $groupIDList, 'developer');
}
$gitlab = $this->gitlab->getByID($gitlabID);
+14 -1
View File
@@ -8,4 +8,17 @@ $(document).ready(function()
$(this).parent().parent().find('.email').text(user.email)
}
});
});
$(document).on('click', '.zentao-users .chosen-container', function()
{
var $obj = $(this).prev('select');
var value = $obj.val();
if($obj.hasClass('filled')) return false;
$obj.empty();
$obj.append($('#userList').html());
$obj.val(value);
$obj.addClass('filled');
$obj.trigger("chosen:updated");
})
});
+20
View File
@@ -14,3 +14,23 @@ window.renderGitlabUser = function(result, {row})
return result;
}
window.bindUser = function()
{
const myDTable = $('#table-gitlab-binduser').zui('dtable');
const formData = myDTable.$.getFormData();
var bindData = $('#table-gitlab-binduser').zui('dtable').$.props.data;
var postData = {};
postData['gitlabUserNames[]'] = [];
for(i in bindData)
{
postData['gitlabUserNames[]'].push(bindData[i].gitlabID);
postData['zentaoUsers[' + bindData[i].gitlabID + ']'] = formData['zentaoUsers[' + bindData[i].gitlabID + ']'];
}
$.ajaxSubmit({
url: $.createLink('gitlab', 'bindUser', 'gitlabID=' + gitlabID + '&type=' + type),
data: postData
});
}
+9 -2
View File
@@ -108,7 +108,9 @@ $lang->gitlab->apiError[2] = 'is too short (minimum is 8 characters)';
$lang->gitlab->apiError[3] = "can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'";
$lang->gitlab->apiError[4] = 'Branch already exists';
$lang->gitlab->apiError[5] = 'Failed to save group {:path=>["has already been taken"]}';
$lang->gitlab->apiError[6] = '403 Forbidden';
$lang->gitlab->apiError[6] = 'Failed to save group {:path=>["已经被使用"]}';
$lang->gitlab->apiError[7] = '403 Forbidden';
$lang->gitlab->apiError[8] = 'is invalid';
$lang->gitlab->errorLang[0] = 'You cannot set Internal as its Visibility Level, if it is private in GitLab.';
$lang->gitlab->errorLang[1] = 'You cannot set Public as its Visibility Level, if it is private in GitLab.';
@@ -116,7 +118,12 @@ $lang->gitlab->errorLang[2] = 'Password is too short (minimum is 8 characters)';
$lang->gitlab->errorLang[3] = 'It should contain only letters, digits, underscore, hyphen and period. It should not start with hypen, or end with .git or .atom.';
$lang->gitlab->errorLang[4] = 'Branch already exists.';
$lang->gitlab->errorLang[5] = 'Failed to save group, path has already been taken.';
$lang->gitlab->errorLang[6] = $lang->gitlab->noAccess;
$lang->gitlab->errorLang[6] = 'Failed to save group, path has already been taken.';
$lang->gitlab->errorLang[7] = $lang->gitlab->noAccess;
$lang->gitlab->errorLang[8] = "Is invalid";
$lang->gitlab->errorResonse['Email has already been taken'] = 'Email has already been taken';
$lang->gitlab->errorResonse['Username has already been taken'] = 'Username has already been taken';
$lang->gitlab->project = new stdclass;
$lang->gitlab->project->id = "Project ID";
+9 -2
View File
@@ -108,7 +108,9 @@ $lang->gitlab->apiError[2] = 'is too short (minimum is 8 characters)';
$lang->gitlab->apiError[3] = "can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'";
$lang->gitlab->apiError[4] = 'Branch already exists';
$lang->gitlab->apiError[5] = 'Failed to save group {:path=>["has already been taken"]}';
$lang->gitlab->apiError[6] = '403 Forbidden';
$lang->gitlab->apiError[6] = 'Failed to save group {:path=>["已经被使用"]}';
$lang->gitlab->apiError[7] = '403 Forbidden';
$lang->gitlab->apiError[8] = 'is invalid';
$lang->gitlab->errorLang[0] = 'You cannot set Internal as its Visibility Level, if it is private in GitLab.';
$lang->gitlab->errorLang[1] = 'You cannot set Public as its Visibility Level, if it is private in GitLab.';
@@ -116,7 +118,12 @@ $lang->gitlab->errorLang[2] = 'Password is too short (minimum is 8 characters)';
$lang->gitlab->errorLang[3] = 'It should contain only letters, digits, underscore, hyphen and period. It should not start with hypen, or end with .git or .atom.';
$lang->gitlab->errorLang[4] = 'Branch already exists.';
$lang->gitlab->errorLang[5] = 'Failed to save group, path has already been taken.';
$lang->gitlab->errorLang[6] = $lang->gitlab->noAccess;
$lang->gitlab->errorLang[6] = 'Failed to save group, path has already been taken.';
$lang->gitlab->errorLang[7] = $lang->gitlab->noAccess;
$lang->gitlab->errorLang[8] = "Is invalid";
$lang->gitlab->errorResonse['Email has already been taken'] = 'Email has already been taken';
$lang->gitlab->errorResonse['Username has already been taken'] = 'Username has already been taken';
$lang->gitlab->project = new stdclass;
$lang->gitlab->project->id = "Project ID";
+16 -1
View File
@@ -108,7 +108,19 @@ $lang->gitlab->apiError[2] = 'is too short (minimum is 8 characters)';
$lang->gitlab->apiError[3] = "can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'";
$lang->gitlab->apiError[4] = 'Branch already exists';
$lang->gitlab->apiError[5] = 'Failed to save group {:path=>["has already been taken"]}';
$lang->gitlab->apiError[6] = '403 Forbidden';
$lang->gitlab->apiError[6] = 'Failed to save group {:path=>["已经被使用"]}';
$lang->gitlab->apiError[7] = '403 Forbidden';
$lang->gitlab->apiError[8] = 'is invalid';
$lang->gitlab->errorLang[0] = 'You cannot set Internal as its Visibility Level, if it is private in GitLab.';
$lang->gitlab->errorLang[1] = 'You cannot set Public as its Visibility Level, if it is private in GitLab.';
$lang->gitlab->errorLang[2] = 'Password is too short (minimum is 8 characters)';
$lang->gitlab->errorLang[3] = 'It should contain only letters, digits, underscore, hyphen and period. It should not start with hypen, or end with .git or .atom.';
$lang->gitlab->errorLang[4] = 'Branch already exists.';
$lang->gitlab->errorLang[5] = 'Failed to save group, path has already been taken.';
$lang->gitlab->errorLang[6] = 'Failed to save group, path has already been taken.';
$lang->gitlab->errorLang[7] = $lang->gitlab->noAccess;
$lang->gitlab->errorLang[8] = "Is invalid";
$lang->gitlab->errorLang[0] = 'You cannot set Internal as its Visibility Level, if it is private in GitLab.';
$lang->gitlab->errorLang[1] = 'You cannot set Public as its Visibility Level, if it is private in GitLab.';
@@ -118,6 +130,9 @@ $lang->gitlab->errorLang[4] = 'Branch already exists.';
$lang->gitlab->errorLang[5] = 'Failed to save group, path has already been taken.';
$lang->gitlab->errorLang[6] = $lang->gitlab->noAccess;
$lang->gitlab->errorResonse['Email has already been taken'] = 'Email has already been taken';
$lang->gitlab->errorResonse['Username has already been taken'] = 'Username has already been taken';
$lang->gitlab->project = new stdclass;
$lang->gitlab->project->id = "Project ID";
$lang->gitlab->project->name = "Project name";
+16 -1
View File
@@ -105,7 +105,19 @@ $lang->gitlab->apiError[2] = 'is too short (minimum is 8 characters)';
$lang->gitlab->apiError[3] = "can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'";
$lang->gitlab->apiError[4] = 'Branch already exists';
$lang->gitlab->apiError[5] = 'Failed to save group {:path=>["has already been taken"]}';
$lang->gitlab->apiError[6] = '403 Forbidden';
$lang->gitlab->apiError[6] = 'Failed to save group {:path=>["已经被使用"]}';
$lang->gitlab->apiError[7] = '403 Forbidden';
$lang->gitlab->apiError[8] = 'is invalid';
$lang->gitlab->errorLang[0] = 'You cannot set Internal as its Visibility Level, if it is private in GitLab.';
$lang->gitlab->errorLang[1] = 'You cannot set Public as its Visibility Level, if it is private in GitLab.';
$lang->gitlab->errorLang[2] = 'Password is too short (minimum is 8 characters)';
$lang->gitlab->errorLang[3] = 'It should contain only letters, digits, underscore, hyphen and period. It should not start with hypen, or end with .git or .atom.';
$lang->gitlab->errorLang[4] = 'Branch already exists.';
$lang->gitlab->errorLang[5] = 'Failed to save group, path has already been taken.';
$lang->gitlab->errorLang[6] = 'Failed to save group, path has already been taken.';
$lang->gitlab->errorLang[7] = $lang->gitlab->noAccess;
$lang->gitlab->errorLang[8] = "Is invalid";
$lang->gitlab->errorLang[0] = 'You cannot set Internal as its Visibility Level, if it is private in GitLab.';
$lang->gitlab->errorLang[1] = 'You cannot set Public as its Visibility Level, if it is private in GitLab.';
@@ -115,6 +127,9 @@ $lang->gitlab->errorLang[4] = 'Branch already exists.';
$lang->gitlab->errorLang[5] = 'Failed to save group, path has already been taken.';
$lang->gitlab->errorLang[6] = $lang->gitlab->noAccess;
$lang->gitlab->errorResonse['Email has already been taken'] = 'Email has already been taken';
$lang->gitlab->errorResonse['Username has already been taken'] = 'Username has already been taken';
$lang->gitlab->project = new stdclass;
$lang->gitlab->project->id = "Project ID";
$lang->gitlab->project->name = "Project name";
+9 -2
View File
@@ -108,7 +108,9 @@ $lang->gitlab->apiError[2] = 'is too short (minimum is 8 characters)';
$lang->gitlab->apiError[3] = "can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'";
$lang->gitlab->apiError[4] = 'Branch already exists';
$lang->gitlab->apiError[5] = 'Failed to save group {:path=>["has already been taken"]}';
$lang->gitlab->apiError[6] = '403 Forbidden';
$lang->gitlab->apiError[6] = 'Failed to save group {:path=>["已经被使用"]}';
$lang->gitlab->apiError[7] = '403 Forbidden';
$lang->gitlab->apiError[8] = 'is invalid';
$lang->gitlab->errorLang[0] = '私有分组的项目,可见性级别不能设为内部。';
$lang->gitlab->errorLang[1] = '私有分组的项目,可见性级别不能设为公开。';
@@ -116,7 +118,12 @@ $lang->gitlab->errorLang[2] = '密码太短(最少8个字符)';
$lang->gitlab->errorLang[3] = "只能包含字母、数字、'.'-'和'.'。不能以'-'开头、以'.git'结尾或以'.atom'结尾。";
$lang->gitlab->errorLang[4] = '分支名已存在。';
$lang->gitlab->errorLang[5] = '保存失败,群组URL路径已经被使用。';
$lang->gitlab->errorLang[6] = $lang->gitlab->noAccess;
$lang->gitlab->errorLang[6] = '保存失败,群组URL路径已经被使用。';
$lang->gitlab->errorLang[7] = $lang->gitlab->noAccess;
$lang->gitlab->errorLang[8] = '格式错误';
$lang->gitlab->errorResonse['Email has already been taken'] = '邮箱已存在';
$lang->gitlab->errorResonse['Username has already been taken'] = '用户名已存在';
$lang->gitlab->project = new stdclass;
$lang->gitlab->project->id = "项目ID";
+9
View File
@@ -98,6 +98,9 @@ $lang->gitlab->apiError[2] = 'is too short (minimum is 8 characters)';
$lang->gitlab->apiError[3] = "can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'";
$lang->gitlab->apiError[4] = 'Branch already exists';
$lang->gitlab->apiError[5] = 'Failed to save group {:path=>["has already been taken"]}';
$lang->gitlab->apiError[6] = 'Failed to save group {:path=>["已经被使用"]}';
$lang->gitlab->apiError[7] = '403 Forbidden';
$lang->gitlab->apiError[8] = 'is invalid';
$lang->gitlab->errorLang[0] = '私有分組的項目,可見性級別不能設為內部。';
$lang->gitlab->errorLang[1] = '私有分組的項目,可見性級別不能設為公開。';
@@ -105,6 +108,12 @@ $lang->gitlab->errorLang[2] = '密碼太短(最少8個字元)';
$lang->gitlab->errorLang[3] = "只能包含字母、數字、'.'-'和'.'。不能以'-'開頭、以'.git'結尾或以'.atom'結尾。";
$lang->gitlab->errorLang[4] = '分支名已存在。';
$lang->gitlab->errorLang[5] = '保存失敗,群組URL路徑已經被使用。';
$lang->gitlab->errorLang[6] = '保存失敗,群組URL路徑已經被使用。';
$lang->gitlab->errorLang[7] = $lang->gitlab->noAccess;
$lang->gitlab->errorLang[8] = '格式错误';
$lang->gitlab->errorResonse['Email has already been taken'] = '邮箱已存在';
$lang->gitlab->errorResonse['Username has already been taken'] = '用户名已存在';
$lang->gitlab->project = new stdclass;
$lang->gitlab->project->id = "項目ID";
+58 -5
View File
@@ -400,11 +400,11 @@ class gitlabModel extends model
* @access public
* @return array
*/
public function getCommits($repo, $entry, $revision = 'HEAD', $type = 'dir', $pager = null, $begin = 0, $end = 0)
public function getCommits($repo, $entry, $revision = 'HEAD', $type = 'dir', $pager = null, $begin = '', $end = '')
{
$scm = $this->app->loadClass('scm');
$scm->setEngine($repo);
$comments = $scm->engine->getCommitsByPath($entry, '', '', isset($pager->recPerPage) ? $pager->recPerPage : 10, isset($pager->pageID) ? $pager->pageID : 1);
$comments = $scm->engine->getCommitsByPath($entry, '', '', isset($pager->recPerPage) ? $pager->recPerPage : 10, isset($pager->pageID) ? $pager->pageID : 1, false, $begin, $end);
if(!is_array($comments)) return array();
if(isset($pager->recTotal)) $pager->recTotal = count($comments) < $pager->recPerPage ? $pager->recPerPage * $pager->pageID : $pager->recPerPage * ($pager->pageID + 1);
@@ -441,6 +441,21 @@ class gitlabModel extends model
return $this->loadModel('pipeline')->update($id);
}
/**
* 设置项目信息。
* Set project data.
*
* @param int $gitlabID
* @param int $projectID
* @param object $project
* @access public
* @return void
*/
public function setProject(int $gitlabID, int $projectID, object $project): void
{
$this->projects[$gitlabID][$projectID] = $project;
}
/**
* Send an api get request.
*
@@ -640,7 +655,7 @@ class gitlabModel extends model
*/
public function apiGetGroups($gitlabID, $orderBy = 'id_desc', $minRole = '', $keyword = '')
{
$apiRoot = $this->getApiRoot($gitlabID);
$apiRoot = $this->getApiRoot($gitlabID, false);
$url = sprintf($apiRoot, "/groups");
if($minRole == 'owner')
{
@@ -1018,7 +1033,7 @@ class gitlabModel extends model
* @access public
* @return object
*/
public function apiGetSingleProject($gitlabID, $projectID, $useUser = false)
public function apiGetSingleProject($gitlabID, $projectID, $useUser = true)
{
if(isset($this->projects[$gitlabID][$projectID])) return $this->projects[$gitlabID][$projectID];
@@ -1252,12 +1267,13 @@ class gitlabModel extends model
* @access public
* @return bool
*/
public function addPushWebhook($repo)
public function addPushWebhook($repo, $token = '')
{
$hook = new stdClass;
$hook->url = common::getSysURL() . '/api.php/v1/gitlab/webhook?repoID='. $repo->id;
$hook->push_events = true;
$hook->merge_requests_events = true;
if($token) $hook->token = $token;
/* Return an empty array if where is one existing webhook. */
if($this->isWebhookExists($repo, $hook->url)) return array();
@@ -2977,4 +2993,41 @@ class gitlabModel extends model
return false;
}
/**
* 判断按钮是否可点击。
* Adjust the action clickable.
*
* @param object $instance
* @param string $action
* @access public
* @return bool
*/
public function isClickable(object $gitlab, string $action): bool
{
return commonModel::hasPriv('space', 'browse');
}
/**
* 判断按钮是否显示在列表页。
* Judge an action is displayed in browse page.
*
* @param object $sonarqube
* @param string $action
* @access public
* @return bool
*/
public static function isDisplay(object $sonarqube, string $action): bool
{
$action = strtolower($action);
if(!commonModel::hasPriv('space', 'browse')) return false;
if(!in_array(strtolower(strtolower($action)), array('browseproject', 'browsegroup', 'browseuser', 'browsebranch', 'browsetag')))
{
if(!commonModel::hasPriv('instance', 'manage')) return false;
}
return true;
}
}
+3 -1
View File
@@ -24,6 +24,8 @@ featureBar
toolbar();
jsVar('zentaoUsers', $zentaoUsers);
jsVar('gitlabID', $gitlabID);
jsVar('type', $type);
$config->gitlab->dtable->bindUser->fieldList['gitlabEmail']['onRenderCell'] = jsRaw('renderGitlabUser');
$config->gitlab->dtable->bindUser->fieldList['zentaoUsers']['controlItems'] = $userPairs;
form
@@ -48,7 +50,7 @@ form
array(
'text' => $lang->save,
'btnType' => 'primary',
'onClick' => jsRaw("() => {\$('#bindForm').trigger('submit')}")
'onClick' => jsRaw("() => {bindUser()}")
),
array(
'text' => $lang->goback,
+13 -23
View File
@@ -15,7 +15,7 @@
<?php js::set('zentaoUsers', $zentaoUsers);?>
<div id="mainContent" class="main-content">
<div class="main-header gitlab-bind">
<?php
<?php
echo html::linkButton('<i class="icon icon-back icon-sm"></i> ' . $lang->goback, $browseLink, 'self', "data-app='{$app->tab}'", 'btn btn-secondary');
$allLink = $this->createLink('gitlab', 'binduser', "gitlabID={$gitlabID}&type=all");
@@ -55,7 +55,6 @@
</thead>
<tbody>
<?php foreach($gitlabUsers as $gitlabUser):?>
<?php if(isset($gitlabUser->zentaoAccount)) continue;?>
<?php echo html::hidden("gitlabUserNames[$gitlabUser->id]", $gitlabUser->realname);?>
<tr>
<td>
@@ -63,30 +62,13 @@
<?php echo $gitlabUser->realname . '@' . $gitlabUser->account;?>
</td>
<td><?php echo $gitlabUser->email;?></td>
<td class="email"><?php echo !empty($matchedResult[$gitlabUser->email]) ? $matchedResult[$gitlabUser->email]['email'] : '';?></td>
<td class='gitlab-user-select'><?php echo html::select("zentaoUsers[$gitlabUser->id]", $userPairs, '', "class='form-control select chosen gitlab-user-bind'" );?></td>
<td><?php echo '<span class="text-red">' . $lang->gitlab->notBind . '</span>';?></td>
</tr>
<?php endforeach;?>
<?php foreach($gitlabUsers as $gitlabUser):?>
<?php if(!isset($gitlabUser->zentaoAccount)) continue;?>
<?php echo html::hidden("gitlabUserNames[$gitlabUser->id]", $gitlabUser->realname);?>
<tr>
<td class="email"><?php echo !empty($gitlabUser->zentaoAccount) ? $zentaoUsers[$gitlabUser->zentaoAccount]->email : '';?></td>
<td class='zentao-users'><?php echo html::select("zentaoUsers[$gitlabUser->id]", $gitlabUser->zentaoUsers, $gitlabUser->zentaoAccount, "class='form-control select chosen gitlab-user-bind'" );?></td>
<td>
<?php echo html::image($gitlabUser->avatar, "height=20 width=20 class='img-circle'");?>
<?php echo $gitlabUser->realname . '@' . $gitlabUser->account;?>
</td>
<td><?php echo $gitlabUser->email;?></td>
<td class="email"><?php echo !empty($matchedResult[$gitlabUser->email]) ? $matchedResult[$gitlabUser->email]['email'] : '';?></td>
<td class='gitlab-user-select'><?php echo html::select("zentaoUsers[$gitlabUser->id]", $userPairs, $gitlabUser->zentaoAccount, "class='form-control select chosen gitlab-user-bind'" );?></td>
<td>
<?php if(in_array($gitlabUser->id, $bindedUsers)):?>
<?php $zentaoAccount = zget($userPairs, $gitlabUser->zentaoAccount, '');?>
<?php if(!empty($zentaoAccount)):?>
<?php if($gitlabUser->binded === 1):?>
<?php echo $lang->gitlab->binded;?>
<?php else:?>
<?php elseif($gitlabUser->binded === 2):?>
<?php echo '<span class="text-red">' . $lang->gitlab->bindedError . '</span>';?>
<?php endif;?>
<?php else:?>
<?php echo '<span class="text-red">' . $lang->gitlab->notBind . '</span>';?>
<?php endif;?>
@@ -106,4 +88,12 @@
</div>
</form>
</div>
<div id="userList" class="hidden">
<?php
foreach($userPairs as $account => $realname)
{
echo "<option value='$account' title='$realname'>$realname</option>";
}
?>
</div>
<?php include '../../common/view/footer.html.php';?>
+5 -5
View File
@@ -20,14 +20,14 @@
</form>
</div>
<div class="btn-toolbar pull-right">
<?php if(common::hasPriv('gitlab', 'create')) common::printLink('gitlab', 'createGroup', "gitlabID=$gitlabID", "<i class='icon icon-plus'></i> " . $lang->gitlab->group->create, '', "class='btn btn-primary'");?>
<?php if(common::hasPriv('instance', 'manage')) common::printLink('gitlab', 'createGroup', "gitlabID=$gitlabID", "<i class='icon icon-plus'></i> " . $lang->gitlab->group->create, '', "class='btn btn-primary'");?>
</div>
</div>
<?php if(empty($gitlabGroupList)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->noData;?></span>
<?php if(common::hasPriv('gitlab', 'create')):?>
<?php if(common::hasPriv('instance', 'manage')):?>
<?php echo html::a($this->createLink('gitlab', 'createGroup', "gitlabID=$gitlabID"), "<i class='icon icon-plus'></i> " . $lang->gitlab->group->create, '', "class='btn btn-info'");?>
<?php endif;?>
</p>
@@ -60,9 +60,9 @@
<td class='c-actions text-left'>
<?php
$isAdmin = ($app->user->admin or in_array($gitlabGroup->id, $adminGroupIDList)) ? true : false;
common::printLink('gitlab', 'manageGroupMembers', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", "<i class='icon icon-team'></i> ", '',"title='{$lang->gitlab->group->manageMembers}' class='btn'");
echo common::buildIconButton('gitlab', 'editGroup', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", '', 'list', 'edit', '', '', false, '', '', 0, $isAdmin);
echo common::buildIconButton('gitlab', 'deleteGroup', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", '', 'list', 'trash', 'hiddenwin', '', false, '', '', 0, $isAdmin);
if($this->gitlab->isDisplay($gitlab, 'manageGroupMembers')) common::printLink('gitlab', 'manageGroupMembers', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", "<i class='icon icon-team'></i> ", '',"title='{$lang->gitlab->group->manageMembers}' class='btn'");
if($this->gitlab->isDisplay($gitlab, 'editGroup')) echo common::buildIconButton('gitlab', 'editGroup', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", '', 'list', 'edit', '', '', false, '', '', 0, $isAdmin);
if($this->gitlab->isDisplay($gitlab, 'deleteGroup')) echo common::buildIconButton('gitlab', 'deleteGroup', "gitlabID=$gitlabID&groupID=$gitlabGroup->id", '', 'list', 'trash', 'hiddenwin', '', false, '', '', 0, $isAdmin);
?>
</td>
</tr>
+16 -15
View File
@@ -22,14 +22,14 @@
</form>
</div>
<div class="btn-toolbar pull-right">
<?php if(common::hasPriv('gitlab', 'createProject')) common::printLink('gitlab', 'createProject', "gitlabID=$gitlabID", "<i class='icon icon-plus'></i> " . $lang->gitlab->project->create, '', "class='btn btn-primary'");?>
<?php if(common::hasPriv('instance', 'manage')) common::printLink('gitlab', 'createProject', "gitlabID=$gitlabID", "<i class='icon icon-plus'></i> " . $lang->gitlab->project->create, '', "class='btn btn-primary'");?>
</div>
</div>
<?php if(empty($gitlabProjectList)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->noData;?></span>
<?php if(empty($keyword) and common::hasPriv('gitlab', 'createProject')):?>
<?php if(empty($keyword) and common::hasPriv('instance', 'manage')):?>
<?php echo html::a($this->createLink('gitlab', 'createProject', "gitlabID=$gitlabID"), "<i class='icon icon-plus'></i> " . $lang->gitlab->project->create, '', "class='btn btn-info'");?>
<?php endif;?>
</p>
@@ -60,19 +60,20 @@
<td class='text' title='<?php echo substr($gitlabProject->last_activity_at, 0, 10);?>'><?php echo substr($gitlabProject->last_activity_at, 0, 10);?></td>
<td class='c-actions'>
<?php
$hasRepoClass = isset($repoPairs[$gitlabProject->id]) ? '' : 'disabled';
$adminerClass = $gitlabProject->adminer ? '' : 'disabled';
$maintainerClass = $gitlabProject->isMaintainer ? '' : 'disabled';
$defaultBranchClass = $gitlabProject->adminer ? '' : 'disabled';
echo common::printIcon('gitlab', 'browseBranch', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'treemap', '', $defaultBranchClass, false, '', $this->lang->gitlab->browseBranch);
echo common::printIcon('gitlab', 'browseTag', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag', '', $defaultBranchClass, false, '', $this->lang->gitlab->browseTag);
echo common::printIcon('gitlab', 'manageBranchPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'branch-lock', '', $defaultBranchClass . ' ' . $maintainerClass, false, '', $this->lang->gitlab->browseBranchPriv);
echo common::printIcon('gitlab', 'manageTagPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag-lock', '', $defaultBranchClass . ' ' . $maintainerClass, false, '', $this->lang->gitlab->browseTagPriv);
echo common::printIcon('gitlab', 'manageProjectMembers', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'team', '', $hasRepoClass);
echo common::printIcon('gitlab', 'createWebhook', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'change', 'hiddenwin', $hasRepoClass);
echo common::printIcon('gitlab', 'importIssue', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'link');
echo common::printIcon('gitlab', 'editProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'edit', '', $adminerClass);
echo common::printIcon('gitlab', 'deleteProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'trash', 'hiddenwin', $adminerClass);
$hasRepoClass = isset($repoPairs[$gitlabProject->id]) ? '' : 'disabled';
$maintainerClass = $gitlabProject->isMaintainer ? '' : 'disabled';
$developerClass = $gitlabProject->isDeveloper ? '' : 'disabled';
$defaultBranchClass = $gitlabProject->adminer || $gitlabProject->isMaintainer ? '' : 'disabled';
if($this->gitlab->isDisplay($gitlab, 'browseBranch')) echo common::printIcon('gitlab', 'browseBranch', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'treemap', '', $developerClass, false, '', $this->lang->gitlab->browseBranch);
if($this->gitlab->isDisplay($gitlab, 'browseTag')) echo common::printIcon('gitlab', 'browseTag', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag', '', $developerClass, false, '', $this->lang->gitlab->browseTag);
if($this->gitlab->isDisplay($gitlab, 'manageBranchPriv')) echo common::printIcon('gitlab', 'manageBranchPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'branch-lock', '', $defaultBranchClass, false, '', $this->lang->gitlab->browseBranchPriv);
if($this->gitlab->isDisplay($gitlab, 'manageTagPriv')) echo common::printIcon('gitlab', 'manageTagPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag-lock', '', $defaultBranchClass, false, '', $this->lang->gitlab->browseTagPriv);
if($this->gitlab->isDisplay($gitlab, 'manageProjectMembers')) echo common::printIcon('gitlab', 'manageProjectMembers', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'team', '', $hasRepoClass);
if($this->gitlab->isDisplay($gitlab, 'createWebhook')) echo common::printIcon('gitlab', 'createWebhook', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'change', 'hiddenwin', $hasRepoClass);
if($this->gitlab->isDisplay($gitlab, 'importIssue')) echo common::printIcon('gitlab', 'importIssue', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'link');
if($this->gitlab->isDisplay($gitlab, 'editProject')) echo common::printIcon('gitlab', 'editProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'edit', '', $defaultBranchClass);
if($this->gitlab->isDisplay($gitlab, 'deleteProject')) echo common::printIcon('gitlab', 'deleteProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'trash', 'hiddenwin', $defaultBranchClass);
?>
</td>
</tr>
+10 -7
View File
@@ -20,6 +20,7 @@ class gogs extends control
{
parent::__construct($moduleName, $methodName);
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
/* This is essential when changing tab(menu) from gogs to repo. */
/* Optional: common::setMenuVars('devops', $this->session->repoID); */
if($this->app->rawMethod != 'binduser') $this->loadModel('ci')->setMenu();
@@ -163,7 +164,7 @@ class gogs extends control
$changes = common::createChanges($oldGogs, $gogs);
$this->loadModel('action')->logHistory($actionID, $changes);
$response['load'] = true;
$response['load'] = $this->createLink('space', 'browse');
$response['result'] = 'success';
return $this->send($response);
}
@@ -195,7 +196,7 @@ class gogs extends control
* @access public
* @return void
*/
public function bindUser(int $gogsID, string $type = 'all')
public function bindUser($gogsID, $type = 'all')
{
$zentaoUsers = $this->dao->select('account,email,realname')->from(TABLE_USER)->fetchAll('account');
$userPairs = $this->loadModel('user')->getPairs('noclosed|noletter');
@@ -203,8 +204,8 @@ class gogs extends control
if($_POST)
{
$this->gogs->bindUser($gogsID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->server->http_referer));
if(dao::isError()) return $this->sendError(dao::getError());
return $this->sendSuccess(array('message' => $this->lang->saveSuccess, 'load' => helper::createLink('space', 'browse')));
}
$userList = array();
@@ -262,11 +263,13 @@ class gogs extends control
$project = urldecode(base64_decode($project));
$branches = $this->gogs->apiGetBranches($gogsID, $project);
$options = "<option value=''></option>";
$options = array();
$options[] = array('text' => '', 'value' => '');;
foreach($branches as $branch)
{
$options .= "<option value='{$branch->name}'>{$branch->name}</option>";
$options[] = array('text' => $branch->name, 'value' => $branch->name);
}
$this->send($options);
return print(json_encode($options));
}
}
+24
View File
@@ -0,0 +1,24 @@
$(document).ready(function()
{
$('.gitlab-user-bind').change(function()
{
var user = zentaoUsers[$(this).val()];
if(user !== undefined)
{
$(this).parent().parent().find('.email').text(user.email)
}
});
$(document).on('click', '.zentao-users .chosen-container', function()
{
var $obj = $(this).prev('select');
var value = $obj.val();
if($obj.hasClass('filled')) return false;
$obj.empty();
$obj.append($('#userList').html());
$obj.val(value);
$obj.addClass('filled');
$obj.trigger("chosen:updated");
})
});
+20
View File
@@ -14,3 +14,23 @@ window.renderGitlabUser = function(result, {row})
return result;
}
window.bindUser = function()
{
const myDTable = $('#table-gogs-binduser').zui('dtable');
const formData = myDTable.$.getFormData();
var bindData = $('#table-gogs-binduser').zui('dtable').$.props.data;
var postData = {};
postData['gogsUserNames[]'] = [];
for(i in bindData)
{
postData['gogsUserNames[]'].push(bindData[i].gogsID);
postData['zentaoUsers[' + bindData[i].gogsID + ']'] = formData['zentaoUsers[' + bindData[i].gogsID + ']'];
}
$.ajaxSubmit({
url: $.createLink('gogs', 'bindUser', 'gogsID=' + gogsID + '&type=' + type),
data: postData
});
}
+1
View File
@@ -13,6 +13,7 @@ $lang->gogs->gogsAccount = 'Gogs Account';
$lang->gogs->gogsEmail = 'Email';
$lang->gogs->zentaoAccount = 'Zentao Account';
$lang->gogs->bindingStatus = 'Binding Status';
$lang->gogs->all = 'All';
$lang->gogs->notBind = 'Not bind';
$lang->gogs->binded = 'Binded';
$lang->gogs->bindDynamic = '%s and Zentao user %s';
+1
View File
@@ -13,6 +13,7 @@ $lang->gogs->gogsAccount = 'Gogs Account';
$lang->gogs->gogsEmail = 'Email';
$lang->gogs->zentaoAccount = 'Zentao Account';
$lang->gogs->bindingStatus = 'Binding Status';
$lang->gogs->all = 'All';
$lang->gogs->notBind = 'Not bind';
$lang->gogs->binded = 'Binded';
$lang->gogs->bindDynamic = '%s and Zentao user %s';
+1
View File
@@ -13,6 +13,7 @@ $lang->gogs->gogsAccount = 'Gogs Account';
$lang->gogs->gogsEmail = 'Email';
$lang->gogs->zentaoAccount = 'Zentao Account';
$lang->gogs->bindingStatus = 'Binding Status';
$lang->gogs->all = 'All';
$lang->gogs->notBind = 'Not bind';
$lang->gogs->binded = 'Binded';
$lang->gogs->bindDynamic = '%s and Zentao user %s';
+1
View File
@@ -13,6 +13,7 @@ $lang->gogs->gogsAccount = 'Gogs用户';
$lang->gogs->gogsEmail = '邮箱';
$lang->gogs->zentaoAccount = '禅道用户';
$lang->gogs->bindingStatus = '绑定状态';
$lang->gogs->all = '全部';
$lang->gogs->notBind = '未绑定';
$lang->gogs->binded = '已绑定';
$lang->gogs->bindDynamic = '%s与禅道用户%s';
+5 -7
View File
@@ -93,9 +93,9 @@ class gogsModel extends model
*
* @param int $gogsID
* @access public
* @return bool
* @return array
*/
public function bindUser(int $gogsID): bool
public function bindUser($gogsID)
{
$userPairs = $this->loadModel('user')->getPairs('noclosed|noletter');
$users = $this->post->zentaoUsers;
@@ -143,8 +143,6 @@ class gogsModel extends model
$this->loadModel('action')->create('gogsuser', $gogsID, 'bind', '', sprintf($this->lang->gogs->bindDynamic, $gogsNames[$openID], $zentaoUsers[$account]->realname));
}
}
return true;
}
/**
@@ -281,7 +279,7 @@ class gogsModel extends model
* @access public
* @return array
*/
public function getMatchedUsers(int $gogsID, array $gogsUsers, array $zentaoUsers): array
public function getMatchedUsers($gogsID, $gogsUsers, $zentaoUsers)
{
$matches = new stdclass;
foreach($gogsUsers as $gogsUser)
@@ -298,9 +296,9 @@ class gogsModel extends model
$matchedUsers = array();
foreach($gogsUsers as $gogsUser)
{
if(isset($bindedUsers[$gogsUser->account]))
if(isset($bindedUsers[$gogsUser->id]))
{
$gogsUser->zentaoAccount = $bindedUsers[$gogsUser->account];
$gogsUser->zentaoAccount = $bindedUsers[$gogsUser->id];
$matchedUsers[$gogsUser->id] = $gogsUser;
continue;
}
+3 -1
View File
@@ -24,6 +24,8 @@ featureBar
toolbar();
jsVar('zentaoUsers', $zentaoUsers);
jsVar('gogsID', $gogsID);
jsVar('type', $type);
$config->gogs->dtable->bindUser->fieldList['gogsEmail']['onRenderCell'] = jsRaw('renderGitlabUser');
$config->gogs->dtable->bindUser->fieldList['zentaoUsers']['controlItems'] = $userPairs;
form
@@ -48,7 +50,7 @@ form
array(
'text' => $lang->save,
'btnType' => 'primary',
'onClick' => jsRaw("() => {\$('#bindForm').trigger('submit')}")
'onClick' => jsRaw("() => {bindUser()}")
),
array(
'text' => $lang->goback,
+48 -34
View File
@@ -11,60 +11,66 @@
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php $browseLink = $this->createLink('gogs', 'browse', ""); ?>
<?php js::set('zentaoUsers', $zentaoUsers);?>
<div id="mainContent" class="main-content">
<div class="main-header">
<h2><?php echo $lang->gogs->bindUser;?></h2>
<div class="main-header gogs-bind">
<?php
echo html::linkButton('<i class="icon icon-back icon-sm"></i> ' . $lang->goback, $browseLink, 'self', "data-app='{$app->tab}'", 'btn btn-secondary');
$allLink = $this->createLink('gogs', 'binduser', "gogsID={$gogsID}&type=all");
$bindedLink = $this->createLink('gogs', 'binduser', "gogsID={$gogsID}&type=binded");
$notBindLink = $this->createLink('gogs', 'binduser', "gogsID={$gogsID}&type=notBind");
if($type == 'all')
{
echo html::linkButton('' . $lang->gogs->all . "<span class='gogs-bind-all'>" . count($gogsUsers) . "</span>", $allLink, 'self', "data-app='{$app->tab}'", 'btn btn-info active');
echo html::linkButton('' . $lang->gogs->notBind, $notBindLink, 'self', "data-app='{$app->tab}'", 'btn btn-info');
echo html::linkButton('' . $lang->gogs->binded, $bindedLink, 'self', "data-app='{$app->tab}'", 'btn btn-info');
}
else if($type == 'binded')
{
echo html::linkButton('' . $lang->gogs->all, $allLink, 'self', "data-app='{$app->tab}'", 'btn btn-info');
echo html::linkButton('' . $lang->gogs->notBind, $notBindLink, 'self', "data-app='{$app->tab}'", 'btn btn-info');
echo html::linkButton('' . $lang->gogs->binded . "<span class='gogs-bind-all'>" . count($gogsUsers) . "</span>", $bindedLink, 'self', "data-app='{$app->tab}'", 'btn btn-info active');
}
else
{
echo html::linkButton('' . $lang->gogs->all, $allLink, 'self', "data-app='{$app->tab}'", 'btn btn-info');
echo html::linkButton('' . $lang->gogs->notBind . "<span class='gogs-bind-all'>" . count($gogsUsers) . "</span>", $notBindLink, 'self', "data-app='{$app->tab}'", 'btn btn-info active');
echo html::linkButton('' . $lang->gogs->binded, $bindedLink, 'self', "data-app='{$app->tab}'", 'btn btn-info');
}
?>
</div>
<form method='post' class='load-indicator main-form form-ajax' enctype='multipart/form-data'>
<div class="table-responsive">
<table class="table table-borderless w-800px">
<table class="table table-borderless">
<thead>
<tr>
<th class='w-60px'><?php echo $lang->gogs->gogsAvatar;?></th>
<th><?php echo $lang->gogs->gogsAccount;?></th>
<th><?php echo $lang->gogs->gogsEmail;?></th>
<th class='w-150px'><?php echo $lang->gogs->zentaoAccount;?></th>
<th><?php echo $lang->gogs->zentaoEmail;?></th>
<th class="w-400px"><?php echo $lang->gogs->zentaoAccount;?> <span class="gogs-account-desc"><?php echo $lang->gogs->accountDesc;?></span></th>
<th><?php echo $lang->gogs->bindingStatus;?></th>
</tr>
</thead>
<tbody>
<?php foreach($gogsUsers as $gogsUser):?>
<?php if(isset($gogsUser->zentaoAccount)) continue;?>
<?php echo html::hidden("gogsUserNames[$gogsUser->account]", $gogsUser->realname);?>
<?php echo html::hidden("gogsUserNames[$gogsUser->id]", $gogsUser->realname);?>
<tr>
<td><?php echo html::image($gogsUser->avatar, "height=40");?></td>
<td class='text-left'>
<strong><?php echo $gogsUser->realname;?></strong>
<br>
<?php echo $gogsUser->account;?>
<td>
<?php echo html::image($gogsUser->avatar, "height=20 width=20 class='img-circle'");?>
<?php echo $gogsUser->realname . '@' . $gogsUser->account;?>
</td>
<td><?php echo $gogsUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$gogsUser->account]", $userPairs, '', "class='form-control select chosen'" );?></td>
<td><?php echo $lang->gogs->notBind;?></td>
</tr>
<?php endforeach;?>
<?php foreach($gogsUsers as $gogsUser):?>
<?php if(!isset($gogsUser->zentaoAccount)) continue;?>
<?php echo html::hidden("gogsUserNames[$gogsUser->account]", $gogsUser->realname);?>
<tr>
<td><?php echo html::image($gogsUser->avatar, "height=40");?></td>
<td class="email"><?php echo !empty($gogsUser->zentaoAccount) ? $zentaoUsers[$gogsUser->zentaoAccount]->email : '';?></td>
<td class='zentao-users'><?php echo html::select("zentaoUsers[$gogsUser->id]", $gogsUser->zentaoUsers, $gogsUser->zentaoAccount, "class='form-control select chosen gogs-user-bind'" );?></td>
<td>
<strong><?php echo $gogsUser->realname;?></strong>
<br>
<?php echo $gogsUser->account;?>
</td>
<td><?php echo $gogsUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$gogsUser->account]", $userPairs, $gogsUser->zentaoAccount, "class='form-control select chosen'" );?></td>
<td>
<?php if(isset($bindedUsers[$gogsUser->zentaoAccount])):?>
<?php $zentaoAccount = zget($userPairs, $gogsUser->zentaoAccount, '');?>
<?php if(!empty($zentaoAccount)):?>
<?php if($gogsUser->binded === 1):?>
<?php echo $lang->gogs->binded;?>
<?php else:?>
<?php elseif($gogsUser->binded === 2):?>
<?php echo '<span class="text-red">' . $lang->gogs->bindedError . '</span>';?>
<?php endif;?>
<?php else:?>
<?php echo $lang->gogs->notBind;?>
<?php echo '<span class="text-red">' . $lang->gogs->notBind . '</span>';?>
<?php endif;?>
</td>
</tr>
@@ -82,4 +88,12 @@
</div>
</form>
</div>
<div id="userList" class="hidden">
<?php
foreach($userPairs as $account => $realname)
{
echo "<option value='$account' title='$realname'>$realname</option>";
}
?>
</div>
<?php include '../../common/view/footer.html.php';?>
+2 -2
View File
@@ -152,7 +152,7 @@ class host extends control
public function delete($id)
{
$this->dao->update(TABLE_HOST)->set('deleted')->eq(1)->where('id')->eq($id)->exec();
$this->loadModel('action')->create('host', $id, 'deleted', '', actionModel::CAN_UNDELETED);
$this->loadModel('action')->create('host', $id, 'deleted', '', $extra = ACTIONMODEL::CAN_UNDELETED);
if(dao::isError())
{
@@ -178,7 +178,7 @@ class host extends control
$reason = $this->lang->host->{$reasonKey};
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
$postData = fixer::input('post')->get();
$postData = fixer::input('post')->skipSpecial('reason')->get();
if(empty($postData->reason))
{
dao::$errors['reason'][] = sprintf($this->lang->error->notempty, $reason);
+4
View File
@@ -0,0 +1,4 @@
.c-name,.c-status,.c-progress,.c-osName{width: 130px;}
.main-header-image{border:none;margin-left: 0!important;padding-left:0;}
.body-modal #mainContent{padding-top: 85px; padding-bottom: 50px;}
.dropdown-menu>li>a {margin: 1px 0;}
+2
View File
@@ -0,0 +1,2 @@
.form-grid .form-label{width: 1rem;}
.form-grid .form-group{padding-left: 1rem;}
+11 -1
View File
@@ -1,2 +1,12 @@
#status {flex-direction: row;}
#hostCreateForm .form-row:last-child {width: 66%;}
#hostCreateForm .form-row:last-child {width: 66%;}
#mainNavbar>.container {padding-top: 8px}
#mainNavbar .nav {justify-content: left; position: relative; left: 0px; top: -4px;}
@media (min-width: 1400px){#mainNavbar .nav {left: -12px;}}
#mainNavbar {background: none;}
#mainNavbar .nav-item>a {padding-right: 0.5rem}
#mainNavbar .nav-item>.active {color: unset; font-weight: 700;}
#mainNavbar .nav-item>a.active:after {position: absolute; content: ''; border-bottom: 2px solid #2e7fff; inset: 0 6px 0 15px;}
.form-grid .form-label{width: 8rem;}
.form-grid .form-group{padding-left: 8rem;}
+60
View File
@@ -0,0 +1,60 @@
var interval;
$(function () {
updateProgressInterval();
});
function updateProgressInterval() {
updateProgress();
interval = setInterval(function ()
{
updateProgress();
}, 3000);
}
function updateProgress() {
$.get(createLink('zahost', 'ajaxImageDownloadProgress', 'hostID=' + hostID)).done(function (response)
{
var result = JSON.parse(response);
var statusList = result.data;
var hasInprogress = false;
for (var imageID in statusList) {
if (statusList[imageID].statusCode) {
if (statusList[imageID].statusCode == 'inprogress' || statusList[imageID].statusCode == 'created' || statusList[imageID].statusCode == 'pending')
{
hasInprogress = true;
$('.image-download-' + imageID).addClass('disabled');
$('.image-cancel-' + imageID).removeClass('disabled');
}
else if (statusList[imageID].statusCode == 'completed')
{
$('.image-path-' + imageID).text(statusList[imageID].path);
$('.image-path-' + imageID).attr('title', statusList[imageID].path);
$('.image-download-' + imageID).addClass('disabled');
$('.image-cancel-' + imageID).addClass('disabled');
$('.image-cancel-' + imageID).attr('href', '#');
$('.image-progress-' + imageID).text("100%");
}
else
{
var link = createLink('zahost', 'downloadImage', "hostID="+hostID+"&imageID="+imageID);
$('.image-download-' + imageID).removeClass('disabled');
$('.image-download-' + imageID).attr('href', link);
$('.image-cancel-' + imageID).addClass('disabled');
$('.image-cancel-' + imageID).attr('href', '#');
$('.image-progress-' + imageID).text('');
}
$('.image-status-' + imageID).text(statusList[imageID].status);
if(statusList[imageID].progress != '' && statusList[imageID].statusCode != 'completed')
{
$('.image-progress-' + imageID).text(statusList[imageID].progress);
}
}
}
if (!hasInprogress)
{
clearInterval(interval)
}
});
}
+81
View File
@@ -0,0 +1,81 @@
var interval;
window.createSortLink = function(col)
{
var sort = col.name + '_asc';
if(sort == orderBy) sort = col.name + '_desc';
return sortLink.replace('{orderBy}', sort);
}
window.renderCell = function(result, {col, row})
{
if(col.name === 'progress')
{
result[0] = {html: "<span class='image-progress-" + row.data.id + "'></span>"};
}
if(col.name === 'path')
{
result[0] = {html: "<span class='image-path-" + row.data.id + "'></span>"};
}
if(col.name === 'status')
{
result[0] = {html: "<span class='image-status-" + row.data.id + "'>" + result[0] + "</span>"};
}
return result;
};
$(function () {
updateProgressInterval();
});
function updateProgressInterval() {
updateProgress();
interval = setInterval(function ()
{
updateProgress();
}, 3000);
}
function updateProgress() {
$.get($.createLink('zahost', 'ajaxImageDownloadProgress', 'hostID=' + hostID)).done(function (response)
{
var result = JSON.parse(response);
var statusList = result.data;
var hasInprogress = false;
for (var imageID in statusList) {
if (statusList[imageID].statusCode) {
if (statusList[imageID].statusCode == 'inprogress' || statusList[imageID].statusCode == 'created' || statusList[imageID].statusCode == 'pending')
{
hasInprogress = true;
}
else if (statusList[imageID].statusCode == 'completed')
{
$('.image-path-' + imageID).text(statusList[imageID].path);
$('.image-path-' + imageID).attr('title', statusList[imageID].path);
$('.image-progress-' + imageID).text("100%");
}
else
{
$('.image-progress-' + imageID).text('');
}
if(statusList[imageID].status != $('.image-status-' + imageID).text()) loadPage();
$('.image-status-' + imageID).text(statusList[imageID].status);
if(statusList[imageID].progress != '' && statusList[imageID].statusCode != 'completed')
{
$('.image-progress-' + imageID).text(statusList[imageID].progress);
}
}
}
if (!hasInprogress)
{
clearInterval(interval)
}
});
}
+1
View File
@@ -110,6 +110,7 @@ $lang->host->pri = 'Priority';
$lang->host->tags = 'Platform Label';
$lang->host->provider = 'Priority';
$lang->host->bridgeID = 'Virtual Bridge';
$lang->host->osNameList['linux'] = 'Linux';
$lang->host->osNameList['windows'] = 'Microsoft Windows';
$lang->host->osNameList['solaris'] = 'Solaris';
+1
View File
@@ -110,6 +110,7 @@ $lang->host->pri = 'Priority';
$lang->host->tags = 'Platform Label';
$lang->host->provider = 'Priority';
$lang->host->bridgeID = 'Virtual Bridge';
$lang->host->osNameList['linux'] = 'Linux';
$lang->host->osNameList['windows'] = 'Microsoft Windows';
$lang->host->osNameList['solaris'] = 'Solaris';
+1
View File
@@ -110,6 +110,7 @@ $lang->host->pri = 'Priority';
$lang->host->tags = 'Platform Label';
$lang->host->provider = 'Priority';
$lang->host->bridgeID = 'Virtual Bridge';
$lang->host->osNameList['linux'] = 'Linux';
$lang->host->osNameList['windows'] = 'Microsoft Windows';
$lang->host->osNameList['solaris'] = 'Solaris';
+6 -4
View File
@@ -83,7 +83,7 @@ class hostModel extends model
$modules = $param ? $this->loadModel('tree')->getAllChildId($param) : '0';
}
$orderBy = str_replace($orderBy, 't1.', '');
$orderBy = str_replace('t1.', '', $orderBy);
$host = $this->dao->select('*,id as hostID')->from(TABLE_HOST)
->where('deleted')->eq('0')
->andWhere('type')->eq('normal')
@@ -157,11 +157,13 @@ class hostModel extends model
->setDefault('cpuNumber,cpuCores,diskSize,memory', 0)
->get();
$hostInfo->admin = intval($hostInfo->admin);
$hostInfo->serverRoom = intval($hostInfo->serverRoom);
$this->dao->update(TABLE_HOST)->data($hostInfo)
->batchCheck($this->config->host->create->requiredFields, 'notempty')
->batchCheck('diskSize,memory', 'float');
if(dao::isError()) return false;
$intFields = explode(',', $this->config->host->create->intFields);
foreach($intFields as $field)
{
@@ -186,7 +188,7 @@ class hostModel extends model
$hostInfo->createdBy = $this->app->user->account;
$hostInfo->createdDate = helper::now();
$this->dao->insert(TABLE_HOST)->data($hostInfo)->autoCheck()->exec();
if(!dao::isError())
if(!dao::isError())
{
$hostID = $this->dao->lastInsertID();
$this->loadModel('action')->create('host', $hostID, 'created');
@@ -219,7 +221,7 @@ class hostModel extends model
->batchCheck($this->config->host->create->requiredFields, 'notempty')
->batchCheck('diskSize,memory', 'float');
if(dao::isError()) return false;
$intFields = explode(',', $this->config->host->create->intFields);
foreach($intFields as $field)
{
+30
View File
@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
/**
* The browseImage view file of host module of ZenTaoPMS.
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Ke Zhao<zhaoke@easycorp.ltd>
* @package host
* @link http://www.zentao.net
*/
namespace zin;
jsVar('hostID', $hostID);
jsVar('orderBy', $orderBy);
jsVar('sortLink', helper::createLink('host', 'browseImage', "hostID={$hostID}&browseType=$browseType&param=$param&orderBy={orderBy}&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}"));
$tableData = initTableData($imageList, $config->host->imageDtable->fieldList);
dtable
(
set::cols(array_values($config->host->imageDtable->fieldList)),
set::data($tableData),
set::sortLink(jsRaw('createSortLink')),
set::onRenderCell(jsRaw('window.renderCell')),
set::footPager(usePager()),
);
render();
+3 -1
View File
@@ -21,7 +21,9 @@ formPanel
formGroup
(
set::name('reason'),
set::control('textarea'),
set::label(' '),
set::control('editor'),
set::required(true),
),
),
);
+63
View File
@@ -0,0 +1,63 @@
<?php
/**
* The image browse view file of zahost module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) 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('hostID', $hostID);?>
<div id='mainMenu' class='clearfix'>
<div class='pull-left btn-toolbar main-header main-header-image'>
<?php echo isonlybody() ? ('<h2><span title="' . $lang->zahost->image->browseImage . '">' . $lang->zahost->image->browseImage . '</span></h2>') : html::a($this->createLink('zahost', 'browseimage', "hostID=$hostID"), "<span class='text'>{$lang->zahost->image->browseImage}</span>", '', "class='btn btn-link btn-active-text'");?>
</div>
</div>
<div id='queryBox' class='cell <?php if($browseType =='bysearch') echo 'show';?>' data-module='vmTemplate'></div>
<div id='mainContent' class='main-table'>
<?php $vars = "hostID=$hostID&browseType=all&param=0&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}";?>
<?php if(empty($imageList)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->zahost->image->imageEmpty;?></span>
</p>
</div>
<?php else:?>
<table class='table has-sort-head table-fixed' id='imageList'>
<thead>
<tr>
<th class='c-name'><?php common::printOrderLink('name', $orderBy, $vars, $lang->zahost->image->name);?></th>
<th class='c-osName'><?php common::printOrderLink('osName', $orderBy, $vars, $lang->zahost->image->os);?></th>
<th class='c-status'><?php echo $lang->zahost->status;?></th>
<th class='c-path'><?php echo $lang->zahost->image->path;?></th>
<th class='c-progress'><?php echo $lang->zahost->image->progress;?></th>
<th class='c-actions-3'><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
<?php foreach($imageList as $image):?>
<tr>
<?php $path = $image->status == 'completed' ? zget($image, 'path', '') : '';?>
<td title="<?php echo $image->name;?>"><?php echo $image->name;?></td>
<td><?php echo $image->osName;?></td>
<td class='image-status-<?php echo zget($image, 'id', 0);?>'><?php echo zget($lang->zahost->image->statusList, $image->status, '');?></td>
<td title="<?php echo $path;?>" class='image-path-<?php echo zget($image, 'id', 0);?>'><?php echo $path?></td>
<td class="image-progress-<?php echo zget($image, 'id', 0);?>"></td>
<td class='c-actions'>
<?php if(common::hasPriv('zahost', 'downloadImage')) echo html::a($this->createLink('zahost', 'downloadImage', "hostID={$hostID}&imageID={$image->id}"), '<i class="icon-download"></i>', 'hiddenwin', zget($image, 'downloadMisc', ''));?>
<?php if(common::hasPriv('zahost', 'cancelDownload')) echo html::a($this->createLink('zahost', 'cancelDownload', "id={$image->id}"), '<i class="icon-ban-circle"></i>', 'hiddenwin', zget($image, 'cancelMisc', ''));?>
</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';?>
+21 -21
View File
@@ -21,31 +21,31 @@ $config->instance->enableAutoRestore = in_array('auto-rollback', $features);
global $lang, $app;
$app->loadLang('space');
$config->instance->actionList['start']['icon'] = 'play';
$config->instance->actionList['start']['className'] = 'ajax-submit';
$config->instance->actionList['start']['hint'] = $lang->instance->start;
$config->instance->actionList['start']['text'] = $lang->instance->start;
$config->instance->actionList['start']['url'] = array('module' => 'instance', 'method' => 'ajaxStart', 'params' => 'id={id}');
$config->instance->actionList['ajaxStart']['icon'] = 'play';
$config->instance->actionList['ajaxStart']['className'] = 'ajax-submit';
$config->instance->actionList['ajaxStart']['hint'] = $lang->instance->start;
$config->instance->actionList['ajaxStart']['text'] = $lang->instance->start;
$config->instance->actionList['ajaxStart']['url'] = array('module' => 'instance', 'method' => 'ajaxStart', 'params' => 'id={id}');
$config->instance->actionList['stop']['icon'] = 'off';
$config->instance->actionList['stop']['className'] = 'ajax-submit';
$config->instance->actionList['stop']['hint'] = $lang->instance->stop;
$config->instance->actionList['stop']['text'] = $lang->instance->stop;
$config->instance->actionList['stop']['data-confirm'] = $lang->instance->notices['confirmStop'];
$config->instance->actionList['stop']['url'] = array('module' => 'instance', 'method' => 'ajaxStop', 'params' => 'id={id}');
$config->instance->actionList['ajaxStop']['icon'] = 'off';
$config->instance->actionList['ajaxStop']['className'] = 'ajax-submit';
$config->instance->actionList['ajaxStop']['hint'] = $lang->instance->stop;
$config->instance->actionList['ajaxStop']['text'] = $lang->instance->stop;
$config->instance->actionList['ajaxStop']['data-confirm'] = $lang->instance->notices['confirmStop'];
$config->instance->actionList['ajaxStop']['url'] = array('module' => 'instance', 'method' => 'ajaxStop', 'params' => 'id={id}');
$config->instance->actionList['uninstall']['icon'] = 'trash';
$config->instance->actionList['uninstall']['hint'] = $lang->instance->uninstall;
$config->instance->actionList['uninstall']['text'] = $lang->instance->uninstall;
$config->instance->actionList['uninstall']['className'] = 'ajax-submit';
$config->instance->actionList['uninstall']['data-confirm'] = $lang->instance->notices['confirmUninstall'];
$config->instance->actionList['uninstall']['url'] = array('module' => 'instance', 'method' => 'ajaxUninstall', 'params' => 'id={id}');
$config->instance->actionList['ajaxUninstall']['icon'] = 'trash';
$config->instance->actionList['ajaxUninstall']['hint'] = $lang->instance->uninstall;
$config->instance->actionList['ajaxUninstall']['text'] = $lang->instance->uninstall;
$config->instance->actionList['ajaxUninstall']['className'] = 'ajax-submit';
$config->instance->actionList['ajaxUninstall']['data-confirm'] = $lang->instance->notices['confirmUninstall'];
$config->instance->actionList['ajaxUninstall']['url'] = array('module' => 'instance', 'method' => 'ajaxUninstall', 'params' => 'id={id}&type={type}');
$config->instance->actionList['visit']['icon'] = 'menu-my';
$config->instance->actionList['visit']['hint'] = $lang->instance->visit;
$config->instance->actionList['visit']['text'] = $lang->instance->visit;
$config->instance->actionList['visit']['target'] = '_blank';
$config->instance->actionList['visit']['url'] = array('module' => 'instance', 'method' => 'visit', 'params' => 'id={id}');
$config->instance->actionList['visit']['url'] = array('module' => 'instance', 'method' => 'visit', 'params' => 'id={id}&externalID={externalID}');
$config->instance->actionList['upgrade']['icon'] = 'refresh';
$config->instance->actionList['upgrade']['data-toggle'] = 'modal';
@@ -56,7 +56,7 @@ $config->instance->actionList['upgrade']['url'] = helper::createLink('in
$config->instance->actions = new stdclass();
$config->instance->actions->view = array();
$config->instance->actions->view['mainActions'] = array('visit', 'start', 'stop', 'upgrade');
$config->instance->actions->view['suffixActions'] = array('uninstall');
$config->instance->actions->view['mainActions'] = array('visit', 'ajaxStart', 'ajaxStop', 'upgrade');
$config->instance->actions->view['suffixActions'] = array('ajaxUninstall');
$config->instance->devopsApps = array(89 => 'gitea', 58 => 'gitlab', 57 => 'gogs', 59 => 'jenkins', 60 => 'sonarqube', 118 => 'nexus');
$config->instance->devopsApps = array('gitea', 'gitlab', 'jenkins', 'sonarqube', 'nexus');
+156 -29
View File
@@ -37,8 +37,62 @@ class instance extends control
* @access public
* @return void
*/
public function view($id, $recTotal = 0, $recPerPage = 20, $pageID = 1, $tab ='baseinfo' )
public function view($id, $type = 'store', $tab ='baseinfo' )
{
if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
if($type === 'store')
{
$this->storeView($id, $tab);
}
else
{
$instance = $this->loadModel('gitea')->getByID($id);
$instance->status = '';
$instance->source = 'user';
$instance->externalID = $instance->id;
$instance->runDuration = 0;
$instance->appName = $instance->type;
$instance->createdAt = $instance->createdDate;
$instanceMetric = new stdclass();
$instanceMetric->cpu = 0;
$instanceMetric->memory = 0;
$this->view->title = $instance->name;
$this->view->instance = $instance;
$this->view->cloudApp = array();
$this->view->seniorAppList = array();
$this->view->actions = $this->loadModel('action')->getList($instance->type, $id);
$this->view->defaultAccount = '';
$this->view->instanceMetric = $instanceMetric;
$this->view->currentResource = '';
$this->view->customItems = array();
$this->view->backupList = array();
$this->view->hasRestoreLog = false;
$this->view->latestBackup = array();
$this->view->dbList = array();
$this->view->domain = '';
}
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->tab = $tab;
$this->view->type = $type;
$this->display();
}
/**
* Show instance view.
*
* @param int $id
* @param int $recTotal
* @param int $recPerPage
* @param int $page
* @access public
* @return void
*/
protected function storeView($id, $tab ='baseinfo' )
{
if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
$this->loadModel('system');
$this->app->loadLang('system');
@@ -53,9 +107,6 @@ class instance extends control
$instanceMetric = $instanceMetric[$instance->id];
$this->lang->switcherMenu = $this->instance->getSwitcher($instance);
$this->app->loadClass('pager', true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$backupList = array();
$latestBackup = new stdclass;
if($tab == 'backup') $backupList = $this->instance->backupList($instance);
@@ -82,13 +133,18 @@ class instance extends control
$customItems = $this->cne->getCustomItems($instance);
if($instance->status == 'running') $this->instanceZen->saveAuthInfo($instance);
if(in_array($instance->chart, $this->config->instance->devopsApps))
{
$url = strstr(getWebRoot(true), ':', true) . '://' . $instance->domain;
$pipeline = $this->loadModel('pipeline')->getByUrl($url);
$instance->externalID = !empty($pipeline) ? $pipeline->id : 0;
}
$this->view->title = $instance->appName;
$this->view->instance = $instance;
$this->view->cloudApp = $this->loadModel('store')->getAppInfoByChart($instance->chart, $instance->channel, false);
$this->view->seniorAppList = $tab == 'baseinfo' ? $this->instance->seniorAppList($instance, $instance->channel) : array();
$this->view->actions = $this->loadModel('action')->getList('instance', $id);
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->defaultAccount = $this->cne->getDefaultAccount($instance);
$this->view->instanceMetric = $instanceMetric;
$this->view->currentResource = $currentResource;
@@ -99,9 +155,6 @@ class instance extends control
$this->view->dbList = $dbList;
$this->view->domain = $this->cne->getDomain($instance);
$this->view->tab = $tab;
$this->view->pager = $pager;
$this->display();
}
/**
@@ -225,6 +278,7 @@ class instance extends control
*/
public function setting($id)
{
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
$currentResource = new stdclass;
$instance = $this->instance->getByID($id);
$currentResource = $this->cne->getAppConfig($instance);
@@ -302,6 +356,7 @@ class instance extends control
*/
public function upgrade($id)
{
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
$instance = $this->instance->getByID($id);
$instance->latestVersion = $this->store->appLatestVersion($instance->appID, $instance->version);
@@ -342,6 +397,7 @@ class instance extends control
*/
public function visit(int $id, int $externalID = 0): void
{
if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
if(!$externalID)
{
$instance = $this->instance->getByID($id);
@@ -366,6 +422,8 @@ class instance extends control
*/
public function createExternalApp(string $type)
{
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
$this->app->loadModuleConfig('sonarqube');
$this->app->loadLang('pipeline');
@@ -388,6 +446,72 @@ class instance extends control
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('space', 'browse')));
}
/**
* 编辑手工配置外部应用。
* Edit a external app.
*
* @param int $externalID
* @access public
* @return viod
*/
public function editExternalApp(int $externalID)
{
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
$oldApp = $this->loadModel('pipeline')->getByID($externalID);
if($_POST)
{
$this->pipeline->update($externalID);
$app = $this->pipeline->getByID($externalID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->loadModel('action');
$actionID = $this->action->create($app->type, $externalID, 'edited');
$changes = common::createChanges($oldApp, $app);
$this->action->logHistory($actionID, $changes);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true, 'closeModal' => true));
}
$this->app->loadLang('space');
$this->app->loadLang('sonarqube');
$this->view->app = $oldApp;
$this->display();
}
/**
* 删除一个外部应用。
* Delete a external app.
*
* @param int $externalID
* @access public
* @return viod
*/
public function deleteExternalApp(int $externalID)
{
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
$oldApp = $this->loadModel('pipeline')->getByID($externalID);
$actionID = $this->pipeline->delete($externalID, $oldApp->type);
if(!$actionID)
{
$response['result'] = 'fail';
$response['callback'] = sprintf('zui.Modal.alert("%s");', $this->lang->pipeline->delError);
return $this->send($response);
}
$app = $this->pipeline->getByID($externalID);
$changes = common::createChanges($oldApp, $app);
$this->loadModel('action')->logHistory($actionID, $changes);
$response['load'] = true;
$response['message'] = zget($this->lang->instance->notices, 'uninstallSuccess');
$response['result'] = 'success';
return $this->send($response);
}
/**
* (Not used at present.) Install app by custom settings.
*
@@ -406,29 +530,16 @@ class instance extends control
* Install app.
*
* @param int $appID
* @param string $checkResource
* @access public
* @return void
*/
public function install($appID)
public function install(int $appID, string $checkResource = 'true')
{
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
$cloudApp = $this->store->getAppInfo($appID);
if(empty($cloudApp)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->noAppInfo));
if(empty($this->config->demoAccounts))
{
$clusterResource = $this->cne->cneMetrics();
$freeMemory = intval($clusterResource->metrics->memory->allocatable * 0.9); // Remain 10% memory for system.
if($cloudApp->memory > $freeMemory)
{
$cloudApp = $cloudApp;
$gapMemory = helper::formatKB(intval(($cloudApp->memory - $freeMemory)));
$requiredMemory = helper::formatKB(intval($cloudApp->memory));
$freeMemory = helper::formatKB(intval($freeMemory));
return $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->instance->errors->notEnoughMemory, $cloudApp->alias, $requiredMemory, $freeMemory, $gapMemory)));
}
}
$versionList = $this->store->appVersionList($cloudApp->id);
$mysqlList = $this->cne->sharedDBList('mysql');
$pgList = $this->cne->sharedDBList('postgresql');
@@ -456,6 +567,16 @@ class instance extends control
if(!validater::checkLength($customData->customDomain, 20, 2)) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->domainLength));
if(!validater::checkREG($customData->customDomain, '/^[a-z\d]+$/')) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->errors->wrongDomainCharacter));
if($checkResource == 'true')
{
$resource = new stdclass();
$resource->cpu = $cloudApp->cpu;
$resource->memory = $cloudApp->memory;
$result = $this->cne->tryAllocate(array($resource));
if(!isset($result->code) || $result->code != 200) return $this->send(array('callback' => 'alertResource()'));
}
/* If select the version, replace the latest version of App by selected version. */
if($customData->version)
{
@@ -505,15 +626,17 @@ class instance extends control
*/
public function ajaxUninstall($instanceID, $type = '')
{
if($type == 'external')
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
if($type !== 'store')
{
$instance = $this->loadModel('pipeline')->getByID($instanceID);
if(!$instance) return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['success']));
if(!$instance) return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['success'], 'load' => $this->createLink('space', 'browse')));
return $this->send($this->fetch($instance->type, 'delete', array('id' => $instance->id)));
if($instance->type == 'nexus') return $this->deleteExternalApp($instance->id);
return $this->fetch($instance->type, 'delete', array('id' => $instance->id));
}
$instance = $this->instance->getByID($instanceID);
if(!$instance) return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['success']));
if(!$instance) return $this->send(array('result' => 'success', 'message' => $this->lang->instance->notices['success'], 'load' => $this->createLink('space', 'browse')));
$externalApp = $this->loadModel('space')->getExternalAppByApp($instance);
if($externalApp)
@@ -524,7 +647,7 @@ class instance extends control
$success = $this->instance->uninstall($instance);
$this->action->create('instance', $instance->id, 'uninstall', '', json_encode(array('result' => $success, 'app' => array('alias' => $instance->appName, 'app_version' => $instance->version))));
if($success) return $this->send(array('result' => 'success', 'message' => zget($this->lang->instance->notices, 'uninstallSuccess'), 'locate' => $this->createLink('space', 'browse')));
if($success) return $this->send(array('result' => 'success', 'message' => zget($this->lang->instance->notices, 'uninstallSuccess'), 'load' => $this->createLink('space', 'browse')));
return $this->send(array('result' => 'fail', 'message' => zget($this->lang->instance->notices, 'uninstallFail')));
}
@@ -538,6 +661,7 @@ class instance extends control
*/
public function ajaxStart($instanceID)
{
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
$instance = $this->instance->getByID($instanceID);
if(!$instance) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->instanceNotExists));
@@ -558,6 +682,7 @@ class instance extends control
*/
public function ajaxStop($instanceID)
{
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
$instance = $this->instance->getByID($instanceID);
if(!$instance) return $this->send(array('result' => 'fail', 'message' => $this->lang->instance->instanceNotExists));
@@ -656,6 +781,7 @@ class instance extends control
*/
public function ajaxDBAuthUrl()
{
if(!commonModel::hasPriv('space', 'browse')) $this->loadModel('common')->deny('space', 'browse', false);
$post = fixer::input('post')
->setDefault('namespace', 'default')
->setDefault('instanceID', 0)
@@ -689,6 +815,7 @@ class instance extends control
*/
public function ajaxAdjustMemory($instanceID)
{
if(!commonModel::hasPriv('instance', 'manage')) $this->loadModel('common')->deny('instance', 'manage', false);
$postData = fixer::input('post')->get();
/* Check free memory size is enough or not. */
+2 -1
View File
@@ -5,4 +5,5 @@
.progress-container {word-break: keep-all; white-space: nowrap;}
.progress-container i {margin: auto; margin-right: 6px;}
.progress-container .progress {margin: auto; width: 100%; height: .7rem; margin-left: 6px; margin-right: 15px;}
.label-dot {display: inline-block; width: 8px; height: 8px; padding: 0; line-height: 20px; text-indent: -9999em; border-radius: 50%;}
.label-dot {display: inline-block; width: 8px; height: 8px; padding: 0; line-height: 20px; text-indent: -9999em; border-radius: 50%;}
#instanceInfoContainer .table>*>tr>* {padding: .5rem .3rem;}
+71 -15
View File
@@ -1,4 +1,4 @@
window.openAdminer = function()
$('#mainContent').on('click', '.db-management', function()
{
var dbName = $(this).data('dbname');
var dbType = $(this).data('dbtype');
@@ -22,22 +22,78 @@ window.openAdminer = function()
}
}
);
}
});
var reloadTimes = 0;
var refreshTime = 0;
var timer = null;
var currentStatus = instanceStatus;
const postData = new FormData();
postData.append('idList[]', instanceID);
window.afterPageUpdate = function()
{
refreshStatus();
}
function refreshStatus()
{
if(new Date().getTime() - refreshTime < 4000) return;
refreshTime = new Date().getTime();
$.ajaxSubmit({
url: $.createLink('instance', 'ajaxStatus'),
method: 'POST',
data:postData,
onComplete: function(res)
{
if(res.result === 'success')
{
$.each(res.data, function(index, instance)
{
if(instance.status === 'running' && ($('#statusTD').data('reload') === true || $('#memoryRate').data('load') === true))
{
setTimeout(() => {loadCurrentPage();}, 3000);
currentStatus = instance.status;
return;
}
if(currentStatus != instance.status)
{
loadCurrentPage();
currentStatus = instance.status;
return;
}
});
}
timer = setTimeout(() => {refreshStatus()}, 5000);
}
});
}
window.onPageUnmount = function()
{
if(!timer) return;
clearTimeout(timer);
}
$('.copy-btn').on('click', function()
{
var copyText = $(this).parent().find('input');
copyText.show();
copyText[0].select();
document.execCommand("Copy");
copyText.hide();
var that = this;
$(that).tooltip
({
trigger: 'click',
placement: 'bottom',
title: copied,
tipClass: 'success',
show:true
});
setTimeout(function()
{
if(reloadTimes > 20) return;
if($('#statusTD').data('reload') === true || $('#memoryRate').data('load') == true)
{
reloadTimes++;
fetchContent({url: $.createLink('instance', 'view', 'id=' + instanceID),
selector: '#instanceInfoContainer',
id: 'instanceInfoContainer',
target: '#instanceInfoContainer',
});
}
}, 4000);
}
$(that).tooltip('hide');
}, 2000)
})
+58 -43
View File
@@ -1,5 +1,12 @@
<?PHP
$lang->instance = new stdclass;
$lang->instance->common = 'Applications';
$lang->instance->manage = 'Manage Applications';
$lang->instance->view = 'Application Detail';
$lang->instance->ajaxStatus = 'Get Application Status';
$lang->instance->ajaxStart = 'Start Application';
$lang->instance->ajaxStop = 'Stop Application';
$lang->instance->ajaxUninstall = 'Uninstall Application';
$lang->instance->name = 'name';
$lang->instance->appName = 'Application type';
$lang->instance->version = 'version';
@@ -13,7 +20,7 @@ $lang->instance->dbType = 'Database';
$lang->instance->advanceOption = 'Advanced Options';
$lang->instance->baseInfo = 'Basic Information';
$lang->instance->backupAndRestore = 'Backup';
$lang->instance->advanced = 'Advanced';
$lang->instance->advance = 'Advanced';
$lang->instance->enableLDAP = 'Enable LDAP';
$lang->instance->linkLDAP = 'Integrated LDAP';
$lang->instance->enableSMTP = 'Enable SMTP';
@@ -32,8 +39,9 @@ $lang->instance->uninstall = 'delete';
$lang->instance->visit = 'Visit';
$lang->instance->editName = 'Modify Name';
$lang->instance->cpuCore = 'Core';
$lang->instance->scaleble = 'Application level expansion';
$lang->instance->scalable = 'Application level expansion';
$lang->instance->change = 'Modify';
$lang->instance->browseProject = "Project List";
$lang->instance->systemLDAPInactive = 'System LDAP not enabled';
$lang->instance->toSystemLDAP = 'Deactivate';
@@ -50,6 +58,10 @@ $lang->instance->installAt = 'Creation time';
$lang->instance->runDuration = 'Running';
$lang->instance->defaultAccount = 'Default User';
$lang->instance->defaultPassword = 'Default Password';
$lang->instance->account = 'User';
$lang->instance->password = 'Password';
$lang->instance->token = 'Token';
$lang->instance->copied = 'Copy successful';
$lang->instance->operationLog = 'Operation Record';
$lang->instance->installedService = 'Installed Service';
$lang->instance->runningService = 'Running Service';
@@ -92,7 +104,7 @@ $lang->instance->backup->dbName = 'name';
$lang->instance->backup->dbStatus = 'Status';
$lang->instance->backup->dbSpentSeconds = 'Time taken (seconds)';
$lang->instance->backup->dbSize = 'Size';
$lang->instance->backup->volume = 'Data volume';
$lang->instance->backup->volumne = 'Data volume';
$lang->instance->backup->volName = 'name';
$lang->instance->backup->volMountName = 'Mount directory';
$lang->instance->backup->volStatus = 'Status';
@@ -100,7 +112,7 @@ $lang->instance->backup->volSpentSeconds = 'Time taken (seconds)';
$lang->instance->backup->volSize = 'Size';
$lang->instance->backup->lastRestore = 'Last rollback';
$lang->instance->backup->restoreDate = 'Rollback time';
$lang->instance->backup->lastBackupAt = 'Last backup time';
$lang->instance->backup->latestBackupAt = 'Last backup time';
$lang->instance->backup->backupBeforeRestore = 'We recommend that you backup before rolling back!';
$lang->instance->backup->enableAutoBackup = 'Enable automatic backup';
$lang->instance->backup->autoBackup = 'Automatic backup';
@@ -163,7 +175,7 @@ $lang->instance->log->date = 'date';
$lang->instance->log->message = 'Content';
$lang->instance->actionList = array();
$lang->instance->actionList['istall'] = '%s installed';
$lang->instance->actionList['install'] = '%s installed';
$lang->instance->actionList['uninstall'] = '%s deleted';
$lang->instance->actionList['start'] = 'Started %s';
$lang->instance->actionList['stop'] = '%s closed';
@@ -186,39 +198,41 @@ $lang->instance->actionList['autorestore'] = 'The system has perform
$lang->instance->actionList['deleteexpiredbackup'] = 'The system has deleted expired automatic backups';
$lang->instance->sourceList = array();
$lang->instance->sourceList['cloud'] = 'Chancheng Public Market';
$lang->instance->sourceList['cloud'] = 'Store';
$lang->instance->sourceList['local'] = 'Local Market';
$lang->instance->sourceList['user'] = 'User';
$lang->instance->channelList = array();
$lang->instance->channelList['test'] = 'Test version';
$lang->instance->channelList['stable'] = 'stable version';
$lang->instance->statusList = array();
$lang->instance->statusList['istallationFailure'] = 'Installation failed';
$lang->instance->statusList['creating'] = 'Creating';
$lang->instance->statusList['initializing'] = 'initializing';
$lang->instance->statusList['pulling'] = 'Downloading';
$lang->instance->statusList['startup'] = 'Starting';
$lang->instance->statusList['starting'] = 'Starting';
$lang->instance->statusList['running'] = 'Running';
$lang->instance->statusList['spending'] = 'Suspending';
$lang->instance->statusList['suspended'] = 'paused';
$lang->instance->statusList['istalling'] = 'Installing';
$lang->instance->statusList['uninstalling'] = 'Removing';
$lang->instance->statusList['stopping'] = 'Closing';
$lang->instance->statusList['stopped'] = 'Closed';
$lang->instance->statusList['destroying'] = 'Destroying';
$lang->instance->statusList['destroyed'] = 'Destroyed';
$lang->instance->statusList['abnormal'] = 'Abnormal';
$lang->instance->statusList['upgrading'] = 'Updating';
$lang->instance->statusList['unknown'] = 'unknown';
$lang->instance->statusList['installationFail'] = 'Installation failed';
$lang->instance->statusList['creating'] = 'Creating';
$lang->instance->statusList['initializing'] = 'initializing';
$lang->instance->statusList['pulling'] = 'Downloading';
$lang->instance->statusList['startup'] = 'Starting';
$lang->instance->statusList['starting'] = 'Starting';
$lang->instance->statusList['running'] = 'Running';
$lang->instance->statusList['suspending'] = 'Suspending';
$lang->instance->statusList['suspended'] = 'paused';
$lang->instance->statusList['installing'] = 'Installing';
$lang->instance->statusList['uninstalling'] = 'Removing';
$lang->instance->statusList['stopping'] = 'Closing';
$lang->instance->statusList['stopped'] = 'Closed';
$lang->instance->statusList['destroying'] = 'Destroying';
$lang->instance->statusList['destroyed'] = 'Destroyed';
$lang->instance->statusList['abnormal'] = 'Abnormal';
$lang->instance->statusList['upgrading'] = 'Updating';
$lang->instance->statusList['unknown'] = 'unknown';
$lang->instance->statusList['scheduling'] = 'Scheduling';
$lang->instance->htmlStatusesClass = array();
$lang->instance->htmlStatusesClass['running'] = 'success';
$lang->instance->htmlStatusesClass['stopped'] = 'default';
$lang->instance->htmlStatusesClass['abnormal'] = 'danger';
$lang->instance->htmlStatusesClass['istallationFailure'] = 'danger';
$lang->instance->htmlStatusesClass['busy'] = "warning";
$lang->instance->htmlStatusesClass['running'] = 'success';
$lang->instance->htmlStatusesClass['stopped'] = 'default';
$lang->instance->htmlStatusesClass['abnormal'] = 'danger';
$lang->instance->htmlStatusesClass['installationFail'] = 'danger';
$lang->instance->htmlStatusesClass['busy'] = "warning";
$lang->instance->memOptions = array();
$lang->instance->memOptions[128 * 1024] = '128MB';
@@ -244,27 +258,27 @@ $lang->instance->notices['confirmStart'] = 'Are you sure to start the appl
$lang->instance->notices['confirmStop'] = 'Are you sure to close this application?';
$lang->instance->notices['confirmUninstall'] = 'Are you sure to delete this application?';
$lang->instance->notices['startSuccess'] = 'Successfully started';
$lang->instance->notices['startFailure'] = 'Start failed';
$lang->instance->notices['startFail'] = 'Start failed';
$lang->instance->notices['stopSuccess'] = 'Close successfully';
$lang->instance->notices['stopFail'] = 'Close failed';
$lang->instance->notices['uninstallSuccess'] = 'Successfully deleted';
$lang->instance->notices['uninstallFailure'] = 'Delete failed';
$lang->instance->notices['iinstallSuccess'] = 'Installation successful';
$lang->instance->notices['iinstallFailure'] = 'Installation failed';
$lang->instance->notices['uninstallFail'] = 'Delete failed';
$lang->instance->notices['installSuccess'] = 'Installation successful';
$lang->instance->notices['installFail'] = 'Installation failed';
$lang->instance->notices['upgradeSuccess'] = 'Upgrade successful';
$lang->instance->notices['upgradeFailure'] = 'Upgrade failed';
$lang->instance->notices['upgradeFail'] = 'Upgrade failed';
$lang->instance->notices['backupSuccess'] = 'Backup task submitted';
$lang->instance->notices['backupFailure'] = 'Backup failed';
$lang->instance->notices['backupFail'] = 'Backup failed';
$lang->instance->notices['restoreSuccess'] = 'The rollback task has been submitted';
$lang->instance->notices['restoreFailure'] = 'Rollback failed';
$lang->instance->notices['restoreFail'] = 'Rollback failed';
$lang->instance->notices['deleteSuccess'] = 'DeleteSuccess';
$lang->instance->notices['deleteFail'] = 'Delete failed';
$lang->instance->notices['starting'] = 'Starting, please wait...';
$lang->instance->notices['stopping'] = 'Closing, please wait...';
$lang->instance->notices['istalling'] = 'Installing, please wait...';
$lang->instance->notices['installing'] = 'Installing, please wait...';
$lang->instance->notices['uninstalling'] = 'Deleting, please wait...';
$lang->instance->notices['upgrading'] = 'Upgrading, please wait...';
$lang->instance->notices['backup'] = 'Backing up, please wait...';
$lang->instance->notices['backuping'] = 'Backing up, please wait...';
$lang->instance->notices['restoring'] = 'Rolling back, please wait...';
$lang->instance->notices['deleting'] = 'Deleting, please wait...';
$lang->instance->notices['adjusting'] = 'Adjusting, please wait...';
@@ -288,6 +302,7 @@ $lang->instance->notices['enableSMTPSuccess'] = 'Enable SMTP successfully';
$lang->instance->notices['disableSMTPSuccess'] = 'Disable SMTP successfully';
$lang->instance->notices['confirmCustom'] = 'After modifying the custom configuration, the service will automatically restart to make the configuration effective.';
$lang->instance->notices['required'] = 'cannot be empty';
$lang->instance->notices['notEnoughResource'] = 'Insufficient platform resources. Do you want to continue installing?';
$lang->instance->nameChangeTo = '%s is modified to %s.';
$lang->instance->versionChangeTo = 'Upgrade %s to %s.';
@@ -296,8 +311,8 @@ $lang->instance->adjustMemorySize = 'It is recommended to adjust the memory to
$lang->instance->enableAutoBackup = 'Enable automatic backup';
$lang->instance->disableAutoBackup = 'Turn off automatic backup';
$lang->instance->InstanceNotExists = 'Service does not exist';
$lang->instance->capticasTooSmall = 'The number of replicas cannot be less than 1';
$lang->instance->instanceNotExists = 'Service does not exist';
$lang->instance->caplicasTooSmall = 'The number of replicas cannot be less than 1';
$lang->instance->empty = 'Currently no service available';
$lang->instance->noComponent = 'No component, click';
$lang->instance->noHigherVersion = 'No higher version found!';
@@ -323,9 +338,9 @@ $lang->instance->errors->wrongRequestData = 'The submitted data is incorrect
$lang->instance->errors->noDBList = 'No database or inaccessible';
$lang->instance->errors->notFoundDB = 'The database cannot be found';
$lang->instance->errors->dbNameIsEmpty = 'Database name is empty';
$lang->instance->errors->faultToAdjustMemory = 'Failed to adjust memory';
$lang->instance->errors->failToAdjustMemory = 'Failed to adjust memory';
$lang->instance->errors->switchLDAPFailed = 'Modifying LDAP settings failed';
$lang->instance->errors->switchSMTPFailed = 'Modifying SMTP settings failed';
$lang->instance->errors->updateCustomimFailed = 'Modifying custom configuration failed';
$lang->instance->errors->FailToSenior = 'Upgrade to Advanced version failed';
$lang->instance->errors->updateCustomFailed = 'Modifying custom configuration failed';
$lang->instance->errors->failToSenior = 'Upgrade to Advanced version failed';
$lang->instance->errors->failedToUpdateDomain = 'Failed to update domain name';
+20 -6
View File
@@ -1,5 +1,12 @@
<?PHP
$lang->instance = new stdclass;
$lang->instance->common = 'Applications';
$lang->instance->manage = 'Manage Applications';
$lang->instance->view = 'Application Detail';
$lang->instance->ajaxStatus = 'Get Application Status';
$lang->instance->ajaxStart = 'Start Application';
$lang->instance->ajaxStop = 'Stop Application';
$lang->instance->ajaxUninstall = 'Uninstall Application';
$lang->instance->name = 'name';
$lang->instance->appName = 'Application type';
$lang->instance->version = 'version';
@@ -13,7 +20,7 @@ $lang->instance->dbType = 'Database';
$lang->instance->advanceOption = 'Advanced Options';
$lang->instance->baseInfo = 'Basic Information';
$lang->instance->backupAndRestore = 'Backup';
$lang->instance->advance = 'Advanced';
$lang->instance->advance = 'Advanced';
$lang->instance->enableLDAP = 'Enable LDAP';
$lang->instance->linkLDAP = 'Integrated LDAP';
$lang->instance->enableSMTP = 'Enable SMTP';
@@ -34,6 +41,7 @@ $lang->instance->editName = 'Modify Name';
$lang->instance->cpuCore = 'Core';
$lang->instance->scalable = 'Application level expansion';
$lang->instance->change = 'Modify';
$lang->instance->browseProject = "Project List";
$lang->instance->systemLDAPInactive = 'System LDAP not enabled';
$lang->instance->toSystemLDAP = 'Deactivate';
@@ -50,6 +58,10 @@ $lang->instance->installAt = 'Creation time';
$lang->instance->runDuration = 'Running';
$lang->instance->defaultAccount = 'Default User';
$lang->instance->defaultPassword = 'Default Password';
$lang->instance->account = 'User';
$lang->instance->password = 'Password';
$lang->instance->token = 'Token';
$lang->instance->copied = 'Copy successful';
$lang->instance->operationLog = 'Operation Record';
$lang->instance->installedService = 'Installed Service';
$lang->instance->runningService = 'Running Service';
@@ -92,7 +104,7 @@ $lang->instance->backup->dbName = 'name';
$lang->instance->backup->dbStatus = 'Status';
$lang->instance->backup->dbSpentSeconds = 'Time taken (seconds)';
$lang->instance->backup->dbSize = 'Size';
$lang->instance->backup->volume = 'Data volume';
$lang->instance->backup->volumne = 'Data volume';
$lang->instance->backup->volName = 'name';
$lang->instance->backup->volMountName = 'Mount directory';
$lang->instance->backup->volStatus = 'Status';
@@ -100,8 +112,7 @@ $lang->instance->backup->volSpentSeconds = 'Time taken (seconds)';
$lang->instance->backup->volSize = 'Size';
$lang->instance->backup->lastRestore = 'Last rollback';
$lang->instance->backup->restoreDate = 'Rollback time';
$lang->instance->backup->latestBackupAt = 'Last Backup';
$lang->instance->backup->lastBackupAt = 'Last backup time';
$lang->instance->backup->latestBackupAt = 'Last backup time';
$lang->instance->backup->backupBeforeRestore = 'We recommend that you backup before rolling back!';
$lang->instance->backup->enableAutoBackup = 'Enable automatic backup';
$lang->instance->backup->autoBackup = 'Automatic backup';
@@ -164,7 +175,7 @@ $lang->instance->log->date = 'date';
$lang->instance->log->message = 'Content';
$lang->instance->actionList = array();
$lang->instance->actionList['install'] = '%s installed';
$lang->instance->actionList['install'] = '%s installed';
$lang->instance->actionList['uninstall'] = '%s deleted';
$lang->instance->actionList['start'] = 'Started %s';
$lang->instance->actionList['stop'] = '%s closed';
@@ -187,8 +198,9 @@ $lang->instance->actionList['autorestore'] = 'The system has perform
$lang->instance->actionList['deleteexpiredbackup'] = 'The system has deleted expired automatic backups';
$lang->instance->sourceList = array();
$lang->instance->sourceList['cloud'] = 'Chancheng Public Market';
$lang->instance->sourceList['cloud'] = 'Store';
$lang->instance->sourceList['local'] = 'Local Market';
$lang->instance->sourceList['user'] = 'User';
$lang->instance->channelList = array();
$lang->instance->channelList['test'] = 'Test version';
@@ -213,6 +225,7 @@ $lang->instance->statusList['destroyed'] = 'Destroyed';
$lang->instance->statusList['abnormal'] = 'Abnormal';
$lang->instance->statusList['upgrading'] = 'Updating';
$lang->instance->statusList['unknown'] = 'unknown';
$lang->instance->statusList['scheduling'] = 'Scheduling';
$lang->instance->htmlStatusesClass = array();
$lang->instance->htmlStatusesClass['running'] = 'success';
@@ -289,6 +302,7 @@ $lang->instance->notices['enableSMTPSuccess'] = 'Enable SMTP successfully';
$lang->instance->notices['disableSMTPSuccess'] = 'Disable SMTP successfully';
$lang->instance->notices['confirmCustom'] = 'After modifying the custom configuration, the service will automatically restart to make the configuration effective.';
$lang->instance->notices['required'] = 'cannot be empty';
$lang->instance->notices['notEnoughResource'] = 'Insufficient platform resources. Do you want to continue installing?';
$lang->instance->nameChangeTo = '%s is modified to %s.';
$lang->instance->versionChangeTo = 'Upgrade %s to %s.';
+21 -6
View File
@@ -1,5 +1,12 @@
<?PHP
$lang->instance = new stdclass;
$lang->instance->common = 'Applications';
$lang->instance->manage = 'Manage Applications';
$lang->instance->view = 'Application Detail';
$lang->instance->ajaxStatus = 'Get Application Status';
$lang->instance->ajaxStart = 'Start Application';
$lang->instance->ajaxStop = 'Stop Application';
$lang->instance->ajaxUninstall = 'Uninstall Application';
$lang->instance->name = 'name';
$lang->instance->appName = 'Application type';
$lang->instance->version = 'version';
@@ -13,7 +20,7 @@ $lang->instance->dbType = 'Database';
$lang->instance->advanceOption = 'Advanced Options';
$lang->instance->baseInfo = 'Basic Information';
$lang->instance->backupAndRestore = 'Backup';
$lang->instance->advanced = 'Advanced';
$lang->instance->advance = 'Advanced';
$lang->instance->enableLDAP = 'Enable LDAP';
$lang->instance->linkLDAP = 'Integrated LDAP';
$lang->instance->enableSMTP = 'Enable SMTP';
@@ -32,8 +39,9 @@ $lang->instance->uninstall = 'delete';
$lang->instance->visit = 'Visit';
$lang->instance->editName = 'Modify Name';
$lang->instance->cpuCore = 'Core';
$lang->instance->scaleble = 'Application level expansion';
$lang->instance->scalable = 'Application level expansion';
$lang->instance->change = 'Modify';
$lang->instance->browseProject = "Project List";
$lang->instance->systemLDAPInactive = 'System LDAP not enabled';
$lang->instance->toSystemLDAP = 'Deactivate';
@@ -50,6 +58,10 @@ $lang->instance->installAt = 'Creation time';
$lang->instance->runDuration = 'Running';
$lang->instance->defaultAccount = 'Default User';
$lang->instance->defaultPassword = 'Default Password';
$lang->instance->account = 'User';
$lang->instance->password = 'Password';
$lang->instance->token = 'Token';
$lang->instance->copied = 'Copy successful';
$lang->instance->operationLog = 'Operation Record';
$lang->instance->installedService = 'Installed Service';
$lang->instance->runningService = 'Running Service';
@@ -92,7 +104,7 @@ $lang->instance->backup->dbName = 'name';
$lang->instance->backup->dbStatus = 'Status';
$lang->instance->backup->dbSpentSeconds = 'Time taken (seconds)';
$lang->instance->backup->dbSize = 'Size';
$lang->instance->backup->volume = 'Data volume';
$lang->instance->backup->volumne = 'Data volume';
$lang->instance->backup->volName = 'name';
$lang->instance->backup->volMountName = 'Mount directory';
$lang->instance->backup->volStatus = 'Status';
@@ -100,7 +112,7 @@ $lang->instance->backup->volSpentSeconds = 'Time taken (seconds)';
$lang->instance->backup->volSize = 'Size';
$lang->instance->backup->lastRestore = 'Last rollback';
$lang->instance->backup->restoreDate = 'Rollback time';
$lang->instance->backup->lastBackupAt = 'Last backup time';
$lang->instance->backup->latestBackupAt = 'Last backup time';
$lang->instance->backup->backupBeforeRestore = 'We recommend that you backup before rolling back!';
$lang->instance->backup->enableAutoBackup = 'Enable automatic backup';
$lang->instance->backup->autoBackup = 'Automatic backup';
@@ -163,7 +175,7 @@ $lang->instance->log->date = 'date';
$lang->instance->log->message = 'Content';
$lang->instance->actionList = array();
$lang->instance->actionList['istall'] = '%s installed';
$lang->instance->actionList['install'] = '%s installed';
$lang->instance->actionList['uninstall'] = '%s deleted';
$lang->instance->actionList['start'] = 'Started %s';
$lang->instance->actionList['stop'] = '%s closed';
@@ -186,8 +198,9 @@ $lang->instance->actionList['autorestore'] = 'The system has perform
$lang->instance->actionList['deleteexpiredbackup'] = 'The system has deleted expired automatic backups';
$lang->instance->sourceList = array();
$lang->instance->sourceList['cloud'] = 'Chancheng Public Market';
$lang->instance->sourceList['cloud'] = 'Store';
$lang->instance->sourceList['local'] = 'Local Market';
$lang->instance->sourceList['user'] = 'User';
$lang->instance->channelList = array();
$lang->instance->channelList['test'] = 'Test version';
@@ -212,6 +225,7 @@ $lang->instance->statusList['destroyed'] = 'Destroyed';
$lang->instance->statusList['abnormal'] = 'Abnormal';
$lang->instance->statusList['upgrading'] = 'Updating';
$lang->instance->statusList['unknown'] = 'unknown';
$lang->instance->statusList['scheduling'] = 'Scheduling';
$lang->instance->htmlStatusesClass = array();
$lang->instance->htmlStatusesClass['running'] = 'success';
@@ -288,6 +302,7 @@ $lang->instance->notices['enableSMTPSuccess'] = 'Enable SMTP successfully';
$lang->instance->notices['disableSMTPSuccess'] = 'Disable SMTP successfully';
$lang->instance->notices['confirmCustom'] = 'After modifying the custom configuration, the service will automatically restart to make the configuration effective.';
$lang->instance->notices['required'] = 'cannot be empty';
$lang->instance->notices['notEnoughResource'] = 'Insufficient platform resources. Do you want to continue installing?';
$lang->instance->nameChangeTo = '%s is modified to %s.';
$lang->instance->versionChangeTo = 'Upgrade %s to %s.';
+18 -5
View File
@@ -1,5 +1,12 @@
<?php
$lang->instance = new stdclass;
$lang->instance->common = '应用';
$lang->instance->manage = '管理应用';
$lang->instance->view = '应用详情';
$lang->instance->ajaxStatus = '获取应用状态';
$lang->instance->ajaxStart = '启动应用';
$lang->instance->ajaxStop = '关闭应用';
$lang->instance->ajaxUninstall = '卸载应用';
$lang->instance->name = '名称';
$lang->instance->appName = '应用类型';
$lang->instance->version = '版本';
@@ -34,6 +41,7 @@ $lang->instance->editName = '修改名称';
$lang->instance->cpuCore = '核';
$lang->instance->scalable = '应用水平扩容';
$lang->instance->change = '修改';
$lang->instance->browseProject = "项目列表";
$lang->instance->systemLDAPInactive = '未开启系统LDAP';
$lang->instance->toSystemLDAP = '去启用';
@@ -42,7 +50,6 @@ $lang->instance->enableSMTP = '启用SMTP';
$lang->instance->systemSMTPInactive = '未开启系统SMTP';
$lang->instance->toSystemSMTP = '去启用';
$lang->instance->serviceInfo = '服务信息';
$lang->instance->appTemplate = '应用模板';
$lang->instance->source = '来源';
@@ -51,6 +58,10 @@ $lang->instance->installAt = '创建时间';
$lang->instance->runDuration = '已运行';
$lang->instance->defaultAccount = '默认用户';
$lang->instance->defaultPassword = '默认密码';
$lang->instance->account = '用户名';
$lang->instance->password = '密码';
$lang->instance->token = 'Token';
$lang->instance->copied = '复制成功';
$lang->instance->operationLog = '操作记录';
$lang->instance->installedService = '已安装服务';
$lang->instance->runningService = '运行中的服务';
@@ -93,7 +104,7 @@ $lang->instance->backup->dbName = '名称';
$lang->instance->backup->dbStatus = '状态';
$lang->instance->backup->dbSpentSeconds = '耗时(秒)';
$lang->instance->backup->dbSize = '大小';
$lang->instance->backup->volume = '数据卷';
$lang->instance->backup->volumne = '数据卷';
$lang->instance->backup->volName = '名称';
$lang->instance->backup->volMountName = '挂载目录';
$lang->instance->backup->volStatus = '状态';
@@ -187,8 +198,9 @@ $lang->instance->actionList['autorestore'] = '系统执行了自动
$lang->instance->actionList['deleteexpiredbackup'] = '系统删除了过期的自动备份';
$lang->instance->sourceList = array();
$lang->instance->sourceList['cloud'] = '渠成公共市场';
$lang->instance->sourceList['cloud'] = '应用市场';
$lang->instance->sourceList['local'] = '本地市场';
$lang->instance->sourceList['user'] = '手工配置';
$lang->instance->channelList = array();
$lang->instance->channelList['test'] = '测试版';
@@ -213,6 +225,7 @@ $lang->instance->statusList['destroyed'] = '已销毁';
$lang->instance->statusList['abnormal'] = '异常';
$lang->instance->statusList['upgrading'] = '更新中';
$lang->instance->statusList['unknown'] = '未知';
$lang->instance->statusList['scheduling'] = '调度中';
$lang->instance->htmlStatusesClass = array();
$lang->instance->htmlStatusesClass['running'] = 'success';
@@ -289,6 +302,7 @@ $lang->instance->notices['enableSMTPSuccess'] = '启用SMTP成功';
$lang->instance->notices['disableSMTPSuccess'] = '禁用SMTP成功';
$lang->instance->notices['confirmCustom'] = '修改自定义配置后服务将自动重启以使配置生效。';
$lang->instance->notices['required'] = '不能为空';
$lang->instance->notices['notEnoughResource'] = '平台资源不足,要继续安装吗?';
$lang->instance->nameChangeTo = ' %s 修改为 %s 。';
$lang->instance->versionChangeTo = ' %s 升级为 %s 。';
@@ -309,8 +323,7 @@ $lang->instance->appLifeTip = 'demo账号安装的应用有30分钟限
$lang->instance->serialDiff = '查看版本区别';
$lang->instance->descOfSwitchSerial = '您当前使用的是<strong>%s</strong>,想要体验更多高级功能,可升级至%s。';
$lang->instance->toSeniorAttention = '重要提示';
$lang->instance->toSeniorTips = "<ul class='text-danger'><li>版本升级后,无法回退到原版本。</li><li>企业版、旗舰版自安装后免费试用6个月。</li><li>开源版升级到企业版或旗舰版后,试用期最大支持3个用户,
请检查开源版用户数量。超出限制将不可用。</li><li>升级成功后,服务将自动重启。</li><li>为避免造成数据丢失,请您在升级前务必做好数据备份。</li></ul>";
$lang->instance->toSeniorTips = "<ul class='text-danger'><li>版本升级后,无法回退到原版本。</li><li>企业版、旗舰版自安装后免费试用6个月。</li><li>开源版升级到企业版或旗舰版后,试用期最大支持3个用户,请检查开源版用户数量。超出限制将不可用。</li><li>升级成功后,服务将自动重启。</li><li>为避免造成数据丢失,请您在升级前务必做好数据备份。</li></ul>";
$lang->instance->errors = new stdclass;
$lang->instance->errors->domainLength = '域名长度必须介于2-20字符之间';
+65 -41
View File
@@ -49,6 +49,20 @@ class InstanceModel extends model
return $instance;
}
/**
* 根据应用url获取应用信息。
* Get a application by url.
*
* @param string $url
* @access public
* @return object
*/
public function getByUrl(string $url)
{
$url = str_replace(array('https://', 'http://'), '', trim($url));
return $this->dao->select('id')->from(TABLE_INSTANCE)->where('domain')->eq($url)->fetch();
}
/**
* Get by id list.
*
@@ -63,10 +77,10 @@ class InstanceModel extends model
->andWhere('deleted')->eq(0)
->fetchAll('id');
$spaces = $this->dao->select('*')->from(TABLE_SPACE)->where('deleted')->eq(0)->andWhere('id')->in(array_column($instances, 'space'))->fetchAll('id');
$spaces = $this->dao->select('*')->from(TABLE_SPACE)->where('deleted')->eq(0)->andWhere('id')->in(helper::arrayColumn($instances, 'space'))->fetchAll('id');
foreach($instances as $instance) $instance->spaceData = zget($spaces, $instance->space, new stdclass);
$solutionIDList = array_column($instances, 'solution');
$solutionIDList = helper::arrayColumn($instances, 'solution');
$solutions = $this->dao->select('*')->from(TABLE_SOLUTION)->where('id')->in($solutionIDList)->fetchAll('id');
foreach($instances as $instance) $instance->solutionData = zget($solutions, $instance->solution, new stdclass);
@@ -103,13 +117,13 @@ class InstanceModel extends model
*/
public function getByAccount($account = '', $pager = null, $pinned = '', $searchParam = '', $status = 'all')
{
$defaultSpace = $this->loadModel('space')->defaultSpace($account ? $account : $this->app->user->account);
// $defaultSpace = $this->loadModel('space')->defaultSpace($account ? $account : $this->app->user->account);
$instances = $this->dao->select('instance.*')->from(TABLE_INSTANCE)->alias('instance')
->leftJoin(TABLE_SPACE)->alias('space')->on('space.id=instance.space')
->where('instance.deleted')->eq(0)
->andWhere('space.id')->eq($defaultSpace->id)
->beginIF($account)->andWhere('space.owner')->eq($account)->fi()
// ->andWhere('space.id')->eq($defaultSpace->id)
// ->beginIF($account)->andWhere('space.owner')->eq($account)->fi()
->beginIF($pinned)->andWhere('instance.pinned')->eq((int)$pinned)->fi()
->beginIF($searchParam)->andWhere('instance.name')->like("%{$searchParam}%")->fi()
->beginIF($status != 'all')->andWhere('instance.status')->eq($status)->fi()
@@ -119,12 +133,12 @@ class InstanceModel extends model
$spaces = $this->dao->select('*')->from(TABLE_SPACE)
->where('deleted')->eq(0)
->andWhere('id')->in(array_column($instances, 'space'))
->andWhere('id')->in(helper::arrayColumn($instances, 'space'))
->fetchAll('id');
foreach($instances as $instance) $instance->spaceData = zget($spaces, $instance->space, new stdclass);
$solutionIDList = array_column($instances, 'solution');
$solutionIDList = helper::arrayColumn($instances, 'solution');
$solutions = $this->dao->select('*')->from(TABLE_SOLUTION)->where('id')->in($solutionIDList)->fetchAll('id');
foreach($instances as $instance) $instance->solutionData = zget($solutions, $instance->solution, new stdclass);
@@ -143,7 +157,7 @@ class InstanceModel extends model
$spaces = $this->dao->select('*')->from(TABLE_SPACE)
->where('deleted')->eq(0)
->andWhere('id')->in(array_column($instances, 'space'))
->andWhere('id')->in(helper::arrayColumn($instances, 'space'))
->fetchAll('id');
foreach($instances as $instance) $instance->spaceData = zget($spaces, $instance->space, new stdclass);
@@ -330,7 +344,7 @@ class InstanceModel extends model
->andWhere("REPLACE(domain, '.$sysDomain', '')")->like("%.%")
->fetchAll('id');
$spaces = $this->dao->select('*')->from(TABLE_SPACE)->where('deleted')->eq(0)->andWhere('id')->in(array_column($instanceList, 'space'))->fetchAll('id');
$spaces = $this->dao->select('*')->from(TABLE_SPACE)->where('deleted')->eq(0)->andWhere('id')->in(helper::arrayColumn($instanceList, 'space'))->fetchAll('id');
foreach($instanceList as $instance) $instance->spaceData = zget($spaces, $instance->space, new stdclass);
@@ -575,7 +589,7 @@ class InstanceModel extends model
$settingsMap->global->ingress->host = $settingsMap->ingress->host;
}
if(!empty($this->config->instance->devopsApps[$instance->appID]))
if(in_array($instance->chart, $this->config->instance->devopsApps))
{
$settingsMap->ci = new stdclass();
$settingsMap->ci->enabled = true;
@@ -914,7 +928,7 @@ class InstanceModel extends model
*/
public function createInstance($app, $space, $thirdDomain, $name = '', $k8name = '', $channel = 'stable', $snippets = array())
{
if(empty($k8name)) $k8name = "{$app->chart}-{$this->app->user->account}-" . date('YmdHis'); //name rule: chartName-userAccount-YmdHis;
if(empty($k8name)) $k8name = "{$app->chart}-" . date('YmdHis'); //name rule: chartName-userAccount-YmdHis;
$instanceData = new stdclass;
$instanceData->appId = $app->id;
@@ -1518,8 +1532,8 @@ class InstanceModel extends model
$backupList = $result->data;
usort($backupList, function($backup1, $backup2){ return $backup1->create_time < $backup2->create_time; });
$accounts = array_column($backupList, 'creator');
foreach($backupList as $backup) $accounts = array_merge($accounts, array_column($backup->restores, 'creator'));
$accounts = helper::arrayColumn($backupList, 'creator');
foreach($backupList as $backup) $accounts = array_merge($accounts, helper::arrayColumn($backup->restores, 'creator'));
$accounts = array_unique($accounts);
@@ -1652,7 +1666,7 @@ class InstanceModel extends model
->fetchAll();
if(empty($instanceList)) return;
$spaceList = $this->dao->select('*')->from(TABLE_SPACE)->where('id')->in(array_column($instanceList, 'space'))->fetchAll('id');
$spaceList = $this->dao->select('*')->from(TABLE_SPACE)->where('id')->in(helper::arrayColumn($instanceList, 'space'))->fetchAll('id');
foreach($instanceList as $instance)
{
@@ -1710,13 +1724,13 @@ class InstanceModel extends model
*
* @param object $instance
* @param object $metrics
* @param string $type 'bar' is progress bar, 'pie' is progress pie.
* @static
* @access public
* @return mixed
*/
public static function printCpuUsage($instance, $metrics, $type = 'bar')
public static function printCpuUsage($instance, $metrics)
{
if($instance->source === 'user') return array('color' => '', 'tip' => '', 'rate' => '', 'usage' => '', 'limit' => '');
$rate = $instance->status == 'stopped' ? 0 : $metrics->rate;
$tip = "{$rate}% = {$metrics->usage} / {$metrics->limit}";
@@ -1726,14 +1740,7 @@ class InstanceModel extends model
if(empty($color) && $rate >= 0 && $rate < 90) $color = 'important';
if(empty($color) && $rate >= 80) $color = 'danger';
if($type == 'array') return array('color' => $color, 'tip' => $tip, 'rate' => $rate . '%', 'usage' => $metrics->usage, 'limit' => $metrics->limit);
if(strtolower($type) == 'pie') commonModel::printProgressPie($rate, '', $tip);
$valueType = 'percent';
if($instance->status == 'stopped') $valueType = '';
commonModel::printProgressBar($rate, '', $tip, $valueType);
return array('color' => $color, 'tip' => $tip, 'rate' => $rate . '%', 'usage' => $metrics->usage, 'limit' => $metrics->limit);
}
/**
@@ -1741,13 +1748,13 @@ class InstanceModel extends model
*
* @param object $instance
* @param object $metrics
* @param string $type 'bar' is progress bar, 'pie' is progress pie.
* @static
* @access public
* @return mixed
*/
public static function printMemUsage($instance, $metrics, $type = 'bar')
public static function printMemUsage($instance, $metrics)
{
if($instance->source === 'user') return array('color' => '', 'tip' => '', 'rate' => '', 'usage' => '', 'limit' => '');
$rate = $instance->status == 'stopped' ? 0 : $metrics->rate;
$tip = "{$rate}% = " . helper::formatKB($metrics->usage) . ' / ' . helper::formatKB($metrics->limit);
@@ -1757,14 +1764,7 @@ class InstanceModel extends model
if(empty($color) && $rate >= 0 && $rate < 90) $color = 'important';
if(empty($color) && $rate >= 80) $color = 'danger';
if($type == 'array') return array('color' => $color, 'tip' => $tip, 'rate' => $rate . '%', 'usage' => helper::formatKB($metrics->usage), 'limit' => helper::formatKB($metrics->limit));
if(strtolower($type) == 'pie') commonModel::printProgressPie($rate, '', $tip);
$valueType = 'tip';
if($instance->status == 'stopped') $valueType = '';
commonModel::printProgressBar($rate, '', $tip, $valueType);
return array('color' => $color, 'tip' => $tip, 'rate' => $rate . '%', 'usage' => helper::formatKB($metrics->usage), 'limit' => helper::formatKB($metrics->limit));
}
/*
@@ -2054,14 +2054,38 @@ class InstanceModel extends model
public function isClickable(object $instance, string $action): bool
{
if(!isset($instance->type)) $instance->type = 'store';
if($action == 'start') return $instance->type != 'external' ? $this->canDo('start', $instance) : false;
if($action == 'stop') return $instance->type != 'external' ? $this->canDo('stop', $instance) : false;
if($action == 'uninstall') return $instance->type != 'external' && $this->canDo('uninstall', $instance);
if($action == 'visit') return $instance->type != 'external' ? ($instance->domain && $this->canDo('visit', $instance)) : true;
if($action == 'upgrade') return !empty($instance->latestVersion);
if($action == 'bindUser') return ($instance->externalID && in_array($instance->appName, array('GitLab', 'Gitea', 'Gogs'))) ? true : false;
if($action == 'edit') return $instance->type != 'external' ? false : true;
if($instance->type !== 'store')
{
if($action === 'edit' || $action === 'visit') return true;
if($action == 'bindUser') return in_array($instance->appName, array('GitLab', 'Gitea', 'Gogs'));
if($action == 'ajaxUninstall') return true;
return false;
}
if($action == 'ajaxStart') return $this->canDo('start', $instance);
if($action == 'ajaxStop') return $this->canDo('stop', $instance);
if($action == 'ajaxUninstall') return $this->canDo('uninstall', $instance);
if($action == 'visit') return !empty($instance->domain) && $this->canDo('visit', $instance);
if($action == 'upgrade') return !empty($instance->latestVersion) && in_array($instance->status, array('stopped', 'running'));
if($action == 'edit') return false;
if($action == 'bindUser') return in_array($instance->appName, array('GitLab', 'Gitea', 'Gogs'));
return true;
}
/**
* 判断按钮是否显示。
* Adjust the action display.
*
* @param object $instance
* @param string $action
* @access public
* @return bool
*/
public function isDisplay(object $instance, string $action): bool
{
if($action !== 'visit' && !commonModel::hasPriv('instance', 'manage')) return false;
return true;
}
@@ -0,0 +1,59 @@
<?php
declare(strict_types=1);
/**
* The edit externalapp view file of instance module of ZenTaoPMS.
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Zeng gang<zenggang@easycorp.ltd>
* @package instance
* @link https://www.zentao.net
*/
namespace zin;
formPanel
(
set::id('appCreateForm'),
set::title($lang->edit . $lang->space->appType[$app->type]),
set::submitBtnText($lang->save),
set::actions(array('submit', array('text' => $lang->cancel, 'data-type' => 'submit', 'data-dismiss' => 'modal'))),
formRow
(
formGroup
(
set::name('name'),
set::required(true),
set::label($lang->sonarqube->name),
set::value($app->name),
)
),
formRow
(
formGroup
(
set::name('url'),
set::required(true),
set::label($lang->sonarqube->url),
set::value($app->url),
)
),
formRow
(
formGroup
(
set::name('account'),
set::label($lang->sonarqube->account),
set::value($app->account),
)
),
formRow
(
formGroup
(
set::name('password'),
set::label($lang->sonarqube->password),
set::value($app->password),
)
),
);
+2
View File
@@ -24,6 +24,7 @@ formPanel
(
set::name('name'),
set::width('500px'),
set::required(true),
set::label($lang->instance->name),
set::value($instance->name),
)
@@ -35,6 +36,7 @@ formPanel
set::name('memory_kb'),
set::width('250px'),
set::control('picker'),
set::required(true),
set::label($lang->instance->adjustMem),
set::value(intval($currentResource->max->memory / 1024)),
set::items($this->instance->filterMemOptions($currentResource)),
+59 -24
View File
@@ -13,13 +13,27 @@ declare(strict_types=1);
namespace zin;
jsVar('instanceID', $instance->id);
jsVar('copied', $lang->instance->copied);
jsVar('instanceID', $instance->id);
jsVar('instanceStatus', $instance->status);
jsVar('instanceType', $type);
$setting = usePager('pager');
$instance->appName = strtolower($instance->appName);
$cpuInfo = $this->instance->printCpuUsage($instance, $instanceMetric->cpu, 'array');
$memoryInfo = $this->instance->printMemUsage($instance, $instanceMetric->memory, 'array');
$actions = $this->loadModel('common')->buildOperateMenu($instance);
if($type !== 'store')
{
$defaultAccount = new stdclass();
$defaultAccount->username = $instance->account;
$defaultAccount->password = $instance->password;
$defaultAccount->token = $instance->token;
$lang->instance->defaultAccount = $lang->instance->account;
$lang->instance->defaultPassword = $lang->instance->password;
}
$dbListWg = array();
foreach($dbList as $db)
{
@@ -39,11 +53,10 @@ foreach($dbList as $db)
btn
(
$lang->instance->management,
setClass('btn text-primary ghost ' . $disabledClass),
setClass('btn text-primary ghost db-management ' . $disabledClass),
setData('dbname', $db->name),
setData('dbtype', $db->db_type),
setData('id', $instance->id),
on::click('openAdminer'),
)
),
);
@@ -55,10 +68,10 @@ detailHeader(
);
div
(
setClass('flex flex-normal gap-x-5'),
setClass('flex flex-normal gap-x-5 justify-center'),
div
(
setClass('basis-2/3'),
setClass('flex-none w-2/3'),
setID('instanceInfoContainer'),
detailBody
(
@@ -67,26 +80,27 @@ div
/* 应用名称信息图标区块 */
section
(
set::title(''),
div
(
setClass('flex justify-between'),
div
(
setClass('flex basis-full'),
img(set::src($instance->logo), setStyle(array('width' => '50px', 'height' => '50px'))),
$type === 'store' ? img(set::src($instance->logo), setStyle(array('width' => '50px', 'height' => '50px'))) : null,
div
(
setClass('ml-3 flex col gap-y-1 basis-full'),
setClass(($type === 'store' ? 'ml-3' : '') . ' flex col gap-y-1 basis-full'),
div
(
$instance->name, setClass('text-xl'),
span($cloudApp->app_version, setClass('ml-3 label lighter rounded-full'))
$type === 'store' ? span($instance->appVersion, setClass('ml-3 label lighter rounded-full')) : null
),
div
$type === 'store' ? div
(
setClass('flex progress-container'),
set::title($cpuInfo['tip']),
icon('cog-outline text-' . $cpuInfo['color']),
icon('cpu text-' . $cpuInfo['color']),
$lang->instance->cpuUsage,
div
(
@@ -99,7 +113,7 @@ div
setStyle('width', $cpuInfo['rate'])
)
),
icon('desktop text-' . $memoryInfo['color']),
icon('memory text-' . $memoryInfo['color']),
$lang->instance->memUsage,
span
(
@@ -120,10 +134,10 @@ div
setStyle('width', $memoryInfo['rate'])
)
)
),
) : null,
),
),
btn
$type !== 'store' ? null : btn
(
$lang->instance->setting,
setClass('btn ghost'),
@@ -144,18 +158,20 @@ div
setClass('table w-auto max-w-full bordered mt-4'),
h::tr
(
h::th($lang->instance->status),
$type !== 'store' ? null : h::th($lang->instance->status),
h::th($lang->instance->source),
// h::th($lang->instance->appTemplate),
h::th($lang->instance->installBy),
h::th($lang->instance->installAt),
h::th($lang->instance->runDuration),
$defaultAccount ? h::th($lang->instance->defaultAccount) : null,
$defaultAccount ? h::th($lang->instance->defaultPassword) : null,
$type !== 'store' ? null : h::th($lang->instance->runDuration),
!empty($defaultAccount->username) ? h::th($lang->instance->defaultAccount) : null,
!empty($defaultAccount->password) ? h::th($lang->instance->defaultPassword) : null,
!empty($defaultAccount->token) ? h::th($lang->instance->token) : null,
(!in_array($instance->appName, array('gitlab', 'sonarqube'))) ? null : h::th($lang->instance->browseProject),
),
h::tr
(
h::td
$type !== 'store' ? null : h::td
(
setID('statusTD'),
setData('reload', in_array($instance->status, array('creating', 'initializing', 'pulling', 'startup', 'starting', 'suspending', 'installing', 'uninstalling', 'stopping', 'destroying', 'upgrading'))),
@@ -169,9 +185,28 @@ div
// h::td(a(set::href($this->createLink('store', 'appView', "id=$instance->appID")), $instance->appName)),
h::td(zget($users, $instance->createdBy, '')),
h::td(substr($instance->createdAt, 0, 16)),
h::td(common::printDuration($instance->runDuration)),
$defaultAccount ? h::td($defaultAccount->username) : null,
$defaultAccount ? h::td($defaultAccount->password) : null,
$type !== 'store' ? null : h::td(common::printDuration($instance->runDuration)),
!empty($defaultAccount->username) ? h::td($defaultAccount->username) : null,
!empty($defaultAccount->password) ? h::td
(
input(set::type('text'), set::value($defaultAccount->password), set::name('password'), setStyle('display', 'none')),
btn(set::className('copy-btn ghost'),set::icon('copy'))
): null,
!empty($defaultAccount->token) ? h::td
(
input(set::type('text'), set::value($defaultAccount->token), set::name('token'), setStyle('display', 'none')),
btn(set::className('copy-btn ghost'),set::icon('copy'))
): null,
(!in_array($instance->appName, array('gitlab', 'sonarqube'))) ? null : h::td
(
btn
(
$lang->instance->management,
setClass('btn text-primary ghost'),
set::disabled($instance->type === 'store' && $instance->status != 'running'),
set::url(createLink($instance->appName, 'browseProject', "{$instance->appName}ID={$instance->externalID}"))
)
),
)
)
),
@@ -205,10 +240,10 @@ div
),
div
(
setClass('basis-auto'),
setClass('w-1/3'),
history
(
set::commentUrl(createLink('action', 'comment', array('objectType' => 'instance', 'objectID' => $instance->id))),
set::commentUrl(createLink('action', 'comment', array('objectType' => $type === 'store' ? 'instance' : $instance->type, 'objectID' => $instance->id))),
)
)
);
+9 -7
View File
@@ -21,9 +21,9 @@ class instanceZen extends instance
*/
protected function saveAuthInfo(object $instance): void
{
if(empty($this->config->instance->devopsApps[$instance->appID])) return;
if(!in_array($instance->chart, $this->config->instance->devopsApps)) return;
$url = 'https://' . $instance->domain;
$url = strstr(getWebRoot(true), ':', true) . '://' . $instance->domain;
$pipeline = $this->loadModel('pipeline')->getByUrl($url);
if(!empty($pipeline)) return;
@@ -31,19 +31,21 @@ class instanceZen extends instance
if(empty($tempMappings)) return;
$pipeline = new stdclass();
$instance->type = $this->config->instance->devopsApps[$instance->appID];
$instance->type = $instance->chart;
$pipeline->type = $instance->type;
$pipeline->private = md5(strval(rand(10,113450)));
$pipeline->createdBy = 'system';
$pipeline->createdDate = helper::now();
$pipeline->url = $url;
$pipeline->name = $this->generatePipelineName($instance);
$pipeline->token = zget($tempMappings, 'admin_token', '');
$pipeline->account = zget($tempMappings, 'admin_username', '');
$pipeline->password = zget($tempMappings, 'admin_password', '');
$pipeline->token = zget($tempMappings, 'admin_token', '');
$pipeline->token = zget($tempMappings, 'api_token', '');
$pipeline->account = zget($tempMappings, 'z_username', '');
$pipeline->password = zget($tempMappings, 'z_password', '');
if($instance->appID == 60) $pipeline->token = base64_encode($pipeline->token . ':');
if(empty($pipeline->account)) $pipeline->account = zget($tempMappings, 'admin_username', '');
$this->pipeline->create($pipeline);
if(dao::isError()) dao::getError();
}
/**
+1 -1
View File
@@ -78,7 +78,7 @@ $config->job->actionList = array();
$config->job->actionList['compile']['icon'] = 'history';
$config->job->actionList['compile']['text'] = $lang->compile->browse;
$config->job->actionList['compile']['hint'] = $lang->compile->browse;
$config->job->actionList['compile']['url'] = helper::createLink('compile', 'browse',"repoID={repo}&jobID={id}");
$config->job->actionList['compile']['url'] = array('module' => 'compile', 'method' => 'browse', 'params' => "repoID={repo}&jobID={id}");
$config->job->actionList['edit']['icon'] = 'edit';
$config->job->actionList['edit']['text'] = $lang->job->edit;
+30 -10
View File
@@ -95,7 +95,7 @@ class job extends control
$job->buildSpec = urldecode($job->pipeline) . '@' . $job->jenkinsName;
$job->engine = zget($this->lang->job->engineList, $job->engine);
$job->frame = zget($this->lang->job->frameList, $job->frame);
$job->productName = $products[$job->product];
$job->productName = zget($products, $job->product, '');
}
$this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->job->browse;
@@ -144,8 +144,7 @@ class job extends control
}
$this->loadModel('action')->create('job', $jobID, 'created');
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $jobID));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse', "repoID={$this->post->repo}")));
}
$this->loadModel('ci');
@@ -260,6 +259,11 @@ class job extends control
if($jobProduct and $jobProduct->deleted == 0) $products += array($job->product => $jobProduct->name);
}
if($job->frame == 'sonarqube' && $job->sonarqubeServer && $job->projectKey)
{
$this->view->sonarqubeProjectPairs = $this->loadModel('sonarqube')->getProjectPairs($job->sonarqubeServer, $job->projectKey);
}
$this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->job->edit;
$this->view->repoPairs = $repoPairs;
$this->view->gitlabRepos = $gitlabRepos;
@@ -316,7 +320,7 @@ class job extends control
{
$this->app->loadLang('project');
$taskID = $compile->testtask;
$task = $this->loadModel('testtask')->getByID($taskID);
$task = $this->loadModel('testtask')->getById($taskID);
$runs = $this->testtask->getRuns($taskID, 0, 'id');
$cases = array();
@@ -380,18 +384,34 @@ class job extends control
public function exec($jobID)
{
$job = $this->job->getByID($jobID);
if(strtolower($job->engine) == 'gitlab' and (!isset($job->reference) or !$job->reference)) return $this->send(array('result' => 'fail', 'message' => $this->lang->job->setReferenceTips, 'locate' => inlink('edit', "id=$jobID")));
//if(strtolower($job->engine) == 'gitlab' and (!isset($job->reference) or !$job->reference)) return $this->send(array('result' => 'fail', 'message' => $this->lang->job->setReferenceTips, 'locate' => inlink('edit', "id=$jobID")));
$compile = $this->job->exec($jobID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'callback' => sprintf('zui.Modal.alert("%s");', dao::getError())));
if(dao::isError())
{
$errors = '';
foreach(dao::getError() as $error)
{
if(is_array($error))
{
foreach($error as $val)
{
$errors .= $val . '\n';
}
}
else
{
$errors .= $error . '\n';
}
}
return $this->sendError($errors);
}
$this->app->loadLang('compile');
$this->loadModel('action')->create('job', $jobID, 'executed');
$message = sprintf($this->lang->job->sendExec, zget($this->lang->compile->statusList, $compile->status));
$response['result'] = 'success';
$response['callback'] = sprintf('zui.Modal.alert("%s");', $message);
return $this->send($response);
$message = sprintf($this->lang->job->sendExec, zget($this->lang->compile->statusList, $compile->status));
return $this->sendSuccess(array('message' => $message));
}
/**
+1
View File
@@ -1 +1,2 @@
#pipelineDropmenu .icon-angle-right {display: none;}
#pipelineDropmenu .ghost {--tw-ring-color: var(--form-control-border);}
+1
View File
@@ -1 +1,2 @@
#pipelineDropmenu .icon-angle-right {display: none;}
#pipelineDropmenu .ghost {--tw-ring-color: var(--form-control-border);}
+1
View File
@@ -7,6 +7,7 @@ function addItem(event)
window.customCount ++;
$(inputGroup).find('input.custom').attr('id', newName);
$(inputGroup).find('input.paramName').val('');
$(inputGroup).find('input[id="' + newName + '"]').next().attr('for', newName);
obj.closest('.form-group').append($(inputGroup));
}
+6
View File
@@ -201,4 +201,10 @@ $(document).ready(function()
{
$('#jkTask').val($('#pipelineDropmenu button.dropmenu-btn').data('value'));
});
$(document).on('change', 'select.paramValue', function()
{
var paramValue = $(this).val();
paramValue = paramValue.substr(1).toUpperCase();
$(this).prevAll('input').val(paramValue);
});
});
+6
View File
@@ -201,4 +201,10 @@ $(document).ready(function()
{
$('#jkTask').val($('#pipelineDropmenu button.dropmenu-btn').data('value'));
});
$(document).on('change', 'select.paramValue', function()
{
var paramValue = $(this).val();
paramValue = paramValue.substr(1).toUpperCase();
$(this).prevAll('input').val(paramValue);
});
});
+10
View File
@@ -0,0 +1,10 @@
$('#jobCases').html("<iframe id='jobTaskResult' src='" + $.createLink('testtask', 'unitCases', 'taskID=' + $('#jobCases').data('task') + '&orderBy=id_desc&onlybody=yes') + "' width='100%' height='0' scrolling='no'></iframe>");
setTimeout(() => {
var height = $('#jobTaskResult').contents().find(".main-table").height();
$('#jobTaskResult').contents().find("#main").css('min-width', 'auto');
$('#jobTaskResult').css('background', 'white');
$('#jobTaskResult').contents().find("#mainMenu").css('display', 'none');
$('#jobTaskResult').contents().find("a").attr('target', '__blank');
$('#jobTaskResult').contents().find(".main-table").css('padding-top', '0');
$('#jobTaskResult').css('height', height + 40 + 'px');
}, 1000);
+2
View File
@@ -17,6 +17,7 @@ $lang->job->browseAction = 'Pipeline List';
$lang->job->id = 'ID';
$lang->job->name = 'Name';
$lang->job->repo = 'Repo';
$lang->job->branch = 'Branch';
$lang->job->product = $lang->productCommon;
$lang->job->svnDir = 'SVN Tag Watch Path';
$lang->job->jenkins = 'Jenkins';
@@ -60,6 +61,7 @@ $lang->job->repoExists = 'This repository has a build task associated with i
$lang->job->projectExists = 'This SonarQube Project has a build task associated with it『%s』';
$lang->job->mustUseJenkins = 'SonarQube frame is only used if the build engine is JenKins.';
$lang->job->jobIsDeleted = 'This repository is associated with a build task, please view the data from the recycle bin';
$lang->job->selectPipeline = 'Please select a pipeline';
$lang->job->buildTypeList['build'] = 'Only Build';
$lang->job->buildTypeList['buildAndDeploy'] = 'Build And Deploy';

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