view.html.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <?php
  2. /**
  3. * The appview view file of instance module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
  6. * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author Ke Zhao<zhaoke@easycorp.ltd>
  8. * @package instance
  9. * @link https://www.zentao.net
  10. */
  11. namespace zin;
  12. jsVar('copied', $lang->instance->copied);
  13. jsVar('instanceID', $instance->id);
  14. jsVar('instanceStatus', $instance->status);
  15. jsVar('instanceType', $type);
  16. jsVar('inQuickon', $config->inQuickon);
  17. jsVar('confirmBackupTip', $lang->instance->backup->confirmTip);
  18. if(empty($instance->externalID)) $instance->externalID = 0;
  19. $instance->appName = strtolower($instance->appName);
  20. $cpuInfo = $this->instance->printCpuUsage($instance, (object)$instanceMetric->cpu);
  21. $memoryInfo = $this->instance->printStorageUsage($instance, (object)$instanceMetric->memory);
  22. $volumeInfo = $this->instance->printStorageUsage($instance, (object)$instanceMetric->disk);
  23. $actions = $this->loadModel('common')->buildOperateMenu($instance);
  24. if($type !== 'store')
  25. {
  26. $defaultAccount = new stdclass();
  27. $defaultAccount->username = $instance->account;
  28. $defaultAccount->password = $instance->password;
  29. $defaultAccount->token = $instance->token;
  30. $lang->instance->defaultAccount = $lang->instance->account;
  31. $lang->instance->defaultPassword = $lang->instance->password;
  32. }
  33. if(!empty($actions['suffixActions']))
  34. {
  35. foreach($actions['suffixActions'] as $suffix => &$action)
  36. {
  37. if($type == 'store' && $action['icon'] == 'trash' && !empty($action['data-confirm']['message'])) $action['data-confirm']['message'] = $lang->instance->notices['confirmUninstallStoreApp'];
  38. }
  39. }
  40. $dbListWg = array();
  41. foreach($dbList as $db)
  42. {
  43. $disabledClass = $db->ready && commonModel::hasPriv('instance', 'manage') ? '' : 'disabled';
  44. $dbListWg[] = h::tr
  45. (
  46. h::td($db->db_name),
  47. h::td($db->db_type),
  48. h::td
  49. (
  50. setID('dbStatusTD'),
  51. $db->ready ? $lang->instance->dbReady : $lang->instance->dbWaiting,
  52. setClass('text-' . ($db->ready ? 'success' : 'danger'))
  53. ),
  54. h::td
  55. (
  56. btn
  57. (
  58. $lang->instance->management,
  59. setClass('btn text-primary ghost db-management ' . $disabledClass),
  60. setData('dbname', $db->name),
  61. setData('dbtype', $db->db_type),
  62. setData('id', $instance->id),
  63. on::click()->call('loadDBAuthUrl', jsRaw('this'))
  64. )
  65. )
  66. );
  67. }
  68. $hideOperate = !in_array($instance->appName, array('gitlab', 'sonarqube'));
  69. if($instance->appName == 'gitlab' && !$app->user->admin)
  70. {
  71. $openID = $this->loadModel('pipeline')->getOpenIdByAccount($instance->externalID, 'gitlab', $app->user->account);
  72. if(!$openID) $hideOperate = true;
  73. }
  74. detailHeader(to::prefix(''), to::title(''));
  75. div
  76. (
  77. setClass('flex flex-normal gap-x-5 justify-center'),
  78. on::click('.copy-btn')->call('copyText', jsRaw('this')),
  79. div
  80. (
  81. setClass('flex-none w-2/3'),
  82. setID('instanceInfoContainer'),
  83. detailBody
  84. (
  85. sectionList(
  86. /* 应用名称信息图标区块 */
  87. section
  88. (
  89. set::title(''),
  90. div
  91. (
  92. setClass('flex justify-between'),
  93. div
  94. (
  95. setClass('flex basis-full'),
  96. $type === 'store' && !empty($instance->logo) ? img(set::src($instance->logo), setStyle(array('width' => '50px', 'height' => '50px'))) : null,
  97. div
  98. (
  99. setClass(($type === 'store' ? 'ml-3' : '') . ' flex col gap-y-1 basis-full'),
  100. div
  101. (
  102. $instance->name, setClass('text-xl'),
  103. $type === 'store' ? span(setID("appVersion"), $instance->appVersion, setClass('ml-3 label gray-pale rounded-full')) : null
  104. ),
  105. $type === 'store' ? div
  106. (
  107. setID('systemLoad'),
  108. setClass('flex progress-container'),
  109. icon('cpu text-' . $cpuInfo['color']),
  110. $lang->instance->cpuUsage,
  111. div
  112. (
  113. setClass('progress rounded-lg'),
  114. set::title($cpuInfo['tip']),
  115. setStyle('background', "var(--color-{$cpuInfo['color']}-50)"),
  116. div
  117. (
  118. setClass('progress-bar ' . $cpuInfo['color']),
  119. set::role('progressbar'),
  120. setStyle('width', $cpuInfo['rate'])
  121. )
  122. ),
  123. icon('memory text-' . $memoryInfo['color']),
  124. $lang->instance->memUsage,
  125. span
  126. (
  127. setClass('text-gray'),
  128. sprintf($lang->instance->memTotal, helper::formatKB($instanceMetric->memory->limit))
  129. ),
  130. div
  131. (
  132. setClass('progress rounded-lg'),
  133. set::title($memoryInfo['tip']),
  134. setStyle('background', "var(--color-{$memoryInfo['color']}-50)"),
  135. div
  136. (
  137. setID('memoryRate'),
  138. set::role('progressbar'),
  139. setData('load', $instance->status == 'running' && $memoryInfo['rate'] == '0%'),
  140. setClass('progress-bar ' . $memoryInfo['color']),
  141. setStyle('width', $memoryInfo['rate'])
  142. )
  143. ),
  144. !empty($diskSettings->resizable) ? icon('db text-' . $volumeInfo['color']) : null,
  145. !empty($diskSettings->resizable) ? $lang->instance->volUsage: null,
  146. !empty($diskSettings->resizable) ? span
  147. (
  148. setClass('text-gray'),
  149. sprintf($lang->instance->volTotal, helper::formatKB($instanceMetric->disk->limit))
  150. ) : null,
  151. !empty($diskSettings->resizable) ? div
  152. (
  153. setClass('progress rounded-lg'),
  154. set::title($volumeInfo['tip']),
  155. setStyle('background', "var(--color-{$volumeInfo['color']}-50)"),
  156. div
  157. (
  158. setID('volumeRate'),
  159. set::role('progressbar'),
  160. setData('load', $instance->status == 'running' && $volumeInfo['rate'] == '0%'),
  161. setClass('progress-bar ' . $volumeInfo['color']),
  162. setStyle('width', $volumeInfo['rate'])
  163. )
  164. ) : null
  165. ) : null
  166. )
  167. ),
  168. $type !== 'store' ? null : btn
  169. (
  170. $lang->instance->setting,
  171. setClass('btn ghost'),
  172. set::disabled(in_array($instance->status, array('installing', 'initializing', 'uninstalling', 'destroying'))),
  173. set::id('setting'),
  174. set::icon('backend'),
  175. setData('toggle', 'modal'),
  176. setData('size', 'sm'),
  177. set::url(createLink('instance', 'setting', "id={$instance->id}")))
  178. )
  179. ),
  180. /* 基本信息区块 */
  181. section
  182. (
  183. set::title($lang->instance->baseInfo),
  184. h::table
  185. (
  186. setStyle('min-width', '700px'),
  187. setClass('table w-full max-w-full bordered mt-4 text-center store-info'),
  188. h::tr
  189. (
  190. $type !== 'store' ? null : h::th($lang->instance->status),
  191. h::th($lang->instance->source),
  192. // h::th($lang->instance->appTemplate),
  193. h::th($lang->instance->installBy),
  194. h::th($lang->instance->installAt),
  195. $type !== 'store' ? null : h::th($lang->instance->runDuration),
  196. !empty($defaultAccount->username) ? h::th($lang->instance->defaultAccount) : null,
  197. !empty($defaultAccount->password) ? h::th($lang->instance->defaultPassword) : null,
  198. !empty($defaultAccount->token) ? h::th($lang->instance->token) : null,
  199. $hideOperate ? null : h::th($lang->instance->browseProject)
  200. ),
  201. h::tr
  202. (
  203. $type !== 'store' ? null : h::td
  204. (
  205. setID('statusTD'),
  206. setData('status', $instance->status),
  207. setData('reload', in_array($instance->status, array('creating', 'initializing', 'pulling', 'startup', 'starting', 'suspending', 'installing', 'uninstalling', 'stopping', 'destroying', 'upgrading'))),
  208. span
  209. (
  210. setClass('label label-dot mx-1 ' . zget($this->lang->instance->htmlStatusesClass, $instance->status, ''))
  211. ),
  212. zget($this->lang->instance->statusList, $instance->status, ''), setClass('text-' . zget($this->lang->instance->htmlStatusesClass, $instance->status, ''))
  213. ),
  214. h::td(zget($lang->instance->sourceList, $instance->source, '')),
  215. // h::td(a(set::href($this->createLink('store', 'appView', "id=$instance->appID")), $instance->appName)),
  216. h::td(zget($users, $instance->createdBy, '')),
  217. h::td(substr($instance->createdAt, 0, 16)),
  218. $type !== 'store' ? null : h::td(common::printDuration($instance->runDuration)),
  219. !empty($defaultAccount->username) ? h::td($defaultAccount->username) : null,
  220. !empty($defaultAccount->password) ? h::td
  221. (
  222. input(set::type('text'), set::value($defaultAccount->password), set::name('password'), setStyle('display', 'none')),
  223. btn(set::className('copy-btn ghost'),set::icon('copy'))
  224. ): null,
  225. !empty($defaultAccount->token) ? h::td
  226. (
  227. input(set::type('text'), set::value($defaultAccount->token), set::name('token'), setStyle('display', 'none')),
  228. btn(set::className('copy-btn ghost'),set::icon('copy'))
  229. ): null,
  230. $hideOperate ? null : h::td
  231. (
  232. btn
  233. (
  234. $lang->instance->management,
  235. setClass('btn text-primary ghost'),
  236. set::disabled($instance->type === 'store' && $instance->status != 'running'),
  237. set::url(createLink($instance->appName, 'browseProject', "{$instance->appName}ID={$instance->externalID}"))
  238. )
  239. )
  240. )
  241. )
  242. ),
  243. /* 数据库区块 */
  244. empty($dbList) ? null : section
  245. (
  246. set::title($lang->instance->dbList),
  247. h::table
  248. (
  249. setStyle('min-width', '700px'),
  250. setClass('table w-full max-w-full bordered mt-4 text-center store-info'),
  251. h::tr
  252. (
  253. h::th($lang->instance->dbName),
  254. h::th($lang->instance->dbType, setStyle('width', '100px')),
  255. h::th($lang->instance->status, setStyle('width', '100px')),
  256. h::th($lang->instance->action, setStyle('width', '100px'))
  257. ),
  258. $dbListWg
  259. )
  260. ),
  261. /* 应用实例备份块。 */
  262. /* Instance Backup block. */
  263. ($config->inQuickon && $type == 'store' && $instance->name != 'ZenTao') ? section(
  264. set::title($lang->instance->backup->common),
  265. set::id('backupSection'),
  266. div(setClass('flex justify-end'), btn(
  267. set(array
  268. (
  269. 'icon' => 'refresh',
  270. 'class' => 'ghost btn',
  271. 'text' => $lang->instance->backup->operators['manual'] ,
  272. 'data-size' => 'sm',
  273. 'onclick' => "onManualBackup({$instance->id})"
  274. ))
  275. ), btn(
  276. set(array
  277. (
  278. 'icon' => 'backend',
  279. 'class' => 'ghost btn',
  280. 'text' => $lang->instance->backup->operators['settings'] ,
  281. 'url' => createLink('instance', 'backupSettings', "id={$instance->id}"),
  282. 'data-size' => 'sm',
  283. 'data-toggle' => 'modal'
  284. ))
  285. )),
  286. div(setID('backupList'), h::js("if(!$('#backupList').find('.dtable-header-cell').length) loadTarget($.createLink('instance', 'backupList', 'id={$instance->id}'), '#backupList');"))
  287. ) : null
  288. ),
  289. floatToolbar
  290. (
  291. set::object($instance),
  292. isAjaxRequest('modal') ? null : to::prefix(backBtn(
  293. set::icon('back'),
  294. set::className('ghost text-white'),
  295. set::url(createLink('space', 'browse')),
  296. $lang->goback
  297. )),
  298. set::main($actions['mainActions']),
  299. set::suffix($actions['suffixActions'])
  300. )
  301. )
  302. ),
  303. div
  304. (
  305. setClass('w-1/3'),
  306. history
  307. (
  308. set::objectID($instance->id),
  309. set::objectType($type === 'store' ? 'instance' : $instance->type),
  310. set::commentUrl(createLink('action', 'comment', array('objectType' => $type === 'store' ? 'instance' : $instance->type, 'objectID' => $instance->id)))
  311. )
  312. )
  313. );