view.html.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. <?php
  2. /**
  3. * The view file of testreport module of ZenTaoPMS.
  4. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
  5. * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  6. * @author Yuting Wang <wangyuting@easycorp.ltd>
  7. * @package testreport
  8. * @link https://www.zentao.net
  9. */
  10. namespace zin;
  11. $this->session->notHead ? null : detailHeader
  12. (
  13. to::title
  14. (
  15. entityLabel
  16. (
  17. set::entityID($report->id),
  18. set::level(1),
  19. set::text($report->title)
  20. ),
  21. $report->deleted ? span(setClass('label danger'), $lang->testreport->deleted) : null
  22. )
  23. );
  24. $members = '';
  25. foreach(explode(',', $report->members) as $member) $members .= zget($users, $member) . ' ';
  26. $caseCharts = array();
  27. foreach($charts as $chartType => $chartOption)
  28. {
  29. $chartData = $datas[$chartType];
  30. $chartOption = array();
  31. $tableTR = array();
  32. $colorList = array('#5470C6', '#91CC75', '#FAC858', '#EE6666', '#73C0DE', '#3BA272', '#FC8452', '#9A60B4', '#EA7CCC');
  33. foreach($chartData as $key => $data)
  34. {
  35. $color = current($colorList);
  36. $chartOption[] = array('name' => $data->name, 'value' => $data->value);
  37. $tableTR[] = h::tr
  38. (
  39. h::td(label(set::className('label-dot mr-2'), set::style(array('background-color' => $color, '--tw-ring-color' => $color))), $data->name),
  40. h::td($data->value),
  41. h::td(($data->percent * 100) . '%')
  42. );
  43. if(!next($colorList)) reset($colorList);
  44. }
  45. $caseCharts[] = div
  46. (
  47. set::className('mt-6'),
  48. div
  49. (
  50. set::className('flex border'),
  51. cell
  52. (
  53. set::width('50%'),
  54. set::className('border-r chart'),
  55. div(set::className('center text-base font-bold py-2'), $lang->testtask->report->charts[$chartType]),
  56. echarts
  57. (
  58. set::_id('chart-' . $chartType),
  59. set::color($colorList),
  60. set::width('100%'),
  61. set::height('300px'),
  62. set::series
  63. (
  64. array
  65. (
  66. array
  67. (
  68. 'data' => $chartOption,
  69. 'type' => 'pie'
  70. )
  71. )
  72. ),
  73. set::tooltip(array('show' => true, 'formatter' => "{b} : {d}%"))
  74. )
  75. ),
  76. cell
  77. (
  78. set::width('50%'),
  79. h::table
  80. (
  81. set::className('table'),
  82. h::tr
  83. (
  84. h::th($lang->report->item),
  85. h::th(set::width('100px'), $lang->report->value),
  86. h::th(set::width('120px'), $lang->report->percent)
  87. ),
  88. $tableTR
  89. )
  90. )
  91. )
  92. );
  93. }
  94. $tableTR = array();
  95. $colorList = array('#D5D9DF', '#D50000', '#FF9800', '#2098EE', '#009688');
  96. $chartOption = array();
  97. foreach($lang->bug->priList as $key => $value)
  98. {
  99. $color = current($colorList);
  100. $label = $key == 0 ? $lang->null : $value;
  101. $generated = !empty($bugInfo['bugStageGroups'][$key]['generated']) ? $bugInfo['bugStageGroups'][$key]['generated'] : 0;
  102. $legacy = !empty($bugInfo['bugStageGroups'][$key]['legacy']) ? $bugInfo['bugStageGroups'][$key]['legacy'] : 0;
  103. $resolved = !empty($bugInfo['bugStageGroups'][$key]['resolved']) ? $bugInfo['bugStageGroups'][$key]['resolved'] : 0;
  104. $chartOption[] = array('name' => $label, 'type' => 'bar', 'data' => array($generated, $legacy, $resolved));
  105. $tableTR[] = h::tr
  106. (
  107. h::td(label(set::className('label-dot mr-2'), set::style(array('background-color' => $color, '--tw-ring-color' => $color))), $label),
  108. h::td($generated),
  109. h::td($legacy),
  110. h::td($resolved)
  111. );
  112. if(!next($colorList)) reset($colorList);
  113. }
  114. $bugStageChart = div
  115. (
  116. set::className('mt-6'),
  117. div
  118. (
  119. set::className('flex border'),
  120. cell
  121. (
  122. set::width('50%'),
  123. set::className('border-r chart'),
  124. div(set::className('center text-base font-bold py-2'), $lang->testreport->bugStageGroups),
  125. echarts
  126. (
  127. set::_id('chart-bugStageGroups'),
  128. set::color($colorList),
  129. set::width('100%'),
  130. set::height('300px'),
  131. set::xAxis
  132. (
  133. array
  134. (
  135. 'type' => 'category',
  136. 'data' => array($lang->testreport->bugStageList['generated'], $lang->testreport->bugStageList['legacy'], $lang->testreport->bugStageList['resolved'])
  137. )
  138. ),
  139. set::yAxis(array('type' => 'value')),
  140. set::series($chartOption),
  141. set::tooltip(array('trigger' => 'axis', 'axisPointer' => array('type' => 'shadow')))
  142. )
  143. ),
  144. cell
  145. (
  146. set::width('50%'),
  147. h::table
  148. (
  149. set::className('table'),
  150. h::tr
  151. (
  152. h::th($lang->bug->pri),
  153. h::th($lang->testreport->bugStageList['generated']),
  154. h::th($lang->testreport->bugStageList['legacy']),
  155. h::th($lang->testreport->bugStageList['resolved'])
  156. ),
  157. $tableTR
  158. )
  159. )
  160. )
  161. );
  162. $tableTR = array();
  163. $chartOption = array();
  164. $xAxisData = array();
  165. $beginTime = isset($report->begin) ? strtotime($report->begin) : strtotime($begin);
  166. $endTime = isset($report->end) ? strtotime($report->end) : strtotime($end);
  167. foreach(array('generated', 'legacy', 'resolved') as $field)
  168. {
  169. $chartOption[$field] = array('name' => $lang->testreport->bugStageList[$field], 'type' => 'line', 'data' => array());
  170. }
  171. for($time = $beginTime; $time <= $endTime; $time += 86400)
  172. {
  173. $date = date('m-d', $time);
  174. $generated = !empty($bugInfo['bugHandleGroups']['generated'][$date]) ? $bugInfo['bugHandleGroups']['generated'][$date] : 0;
  175. $legacy = !empty($bugInfo['bugHandleGroups']['legacy'][$date]) ? $bugInfo['bugHandleGroups']['legacy'][$date] : 0;
  176. $resolved = !empty($bugInfo['bugHandleGroups']['resolved'][$date]) ? $bugInfo['bugHandleGroups']['resolved'][$date] : 0;
  177. $chartOption['generated']['data'][] = $generated;
  178. $chartOption['legacy']['data'][] = $legacy;
  179. $chartOption['resolved']['data'][] = $resolved;
  180. $xAxisData[] = $date;
  181. $tableTR[] = h::tr
  182. (
  183. h::td(setClass('text-center'), $date),
  184. h::td($generated),
  185. h::td($legacy),
  186. h::td($resolved)
  187. );
  188. }
  189. $chartOption = array_values($chartOption);
  190. $bugHandleChart = div
  191. (
  192. set::className('mt-6'),
  193. div
  194. (
  195. set::className('flex border'),
  196. cell
  197. (
  198. set::width('50%'),
  199. set::className('border-r chart'),
  200. div(set::className('center text-base font-bold py-2'), $lang->testreport->bugHandleGroups),
  201. echarts
  202. (
  203. set::_id('chart-bugHandleGroups'),
  204. set::color(array('#FF9800', '#2098EE', '#009688')),
  205. set::width('100%'),
  206. set::height('300px'),
  207. set::xAxis
  208. (
  209. array
  210. (
  211. 'type' => 'category',
  212. 'data' => $xAxisData
  213. )
  214. ),
  215. set::yAxis(array('type' => 'value')),
  216. set::series($chartOption),
  217. set::tooltip(array('trigger' => 'axis', 'axisPointer' => array('type' => 'shadow')))
  218. )
  219. ),
  220. cell
  221. (
  222. set::width('50%'),
  223. h::table
  224. (
  225. set::className('table'),
  226. h::tr
  227. (
  228. h::th($lang->testreport->date),
  229. h::th(label(set::className('label-dot mr-2'), set::style(array('background-color' => '#FF9800', '--tw-ring-color' => '#FF9800'))), $lang->testreport->bugStageList['generated']),
  230. h::th(label(set::className('label-dot mr-2'), set::style(array('background-color' => '#2098EE', '--tw-ring-color' => '#2098EE'))), $lang->testreport->bugStageList['legacy']),
  231. h::th(label(set::className('label-dot mr-2'), set::style(array('background-color' => '#009688', '--tw-ring-color' => '#009688'))), $lang->testreport->bugStageList['resolved'])
  232. ),
  233. $tableTR
  234. )
  235. )
  236. )
  237. );
  238. $bugCharts = array();
  239. foreach($bugInfo as $infoKey => $infoValue)
  240. {
  241. if($infoKey == 'bugStageGroups' || $infoKey == 'bugHandleGroups') continue;
  242. $list = $infoValue;
  243. if($infoKey == 'bugSeverityGroups') $list = $lang->bug->severityList;
  244. if($infoKey == 'bugStatusGroups') $list = $lang->bug->statusList;
  245. if($infoKey == 'bugResolutionGroups') $list = $lang->bug->resolutionList;
  246. $chartOption = array();
  247. $tableTR = array();
  248. $colorList = array('#5470C6', '#91CC75', '#FAC858', '#EE6666', '#73C0DE', '#3BA272', '#FC8452', '#9A60B4', '#EA7CCC');
  249. $sum = 0;
  250. foreach($infoValue as $value) $sum += $value->value;
  251. foreach($list as $listKey => $listValue)
  252. {
  253. $color = current($colorList);
  254. $name = $listValue;
  255. $value = 0;
  256. if(isset($infoValue[$listKey]))
  257. {
  258. $name = $infoValue[$listKey]->name;
  259. $value = $infoValue[$listKey]->value;
  260. }
  261. if(empty($name) && empty($value)) continue;
  262. $chartOption[] = array('name' => $name, 'value' => $value);
  263. $tableTR[] = h::tr
  264. (
  265. h::td(label(set::className('label-dot mr-2'), set::style(array('background-color' => $color, '--tw-ring-color' => $color))), $name),
  266. h::td($value),
  267. h::td(($sum ? round(($value / $sum * 100), 2) : '0') . '%')
  268. );
  269. if(!next($colorList)) reset($colorList);
  270. }
  271. $bugCharts[] = div
  272. (
  273. set::className('mt-6'),
  274. div
  275. (
  276. set::className('flex border'),
  277. cell
  278. (
  279. set::width('50%'),
  280. set::className('border-r chart'),
  281. div(set::className('center text-base font-bold py-2'), $lang->testreport->{$infoKey}),
  282. echarts
  283. (
  284. set::_id('chart-' . $infoKey),
  285. set::color($colorList),
  286. set::width('100%'),
  287. set::height('300px'),
  288. set::series
  289. (
  290. array
  291. (
  292. array
  293. (
  294. 'data' => $chartOption,
  295. 'type' => 'pie'
  296. )
  297. )
  298. ),
  299. set::tooltip(array('show' => true, 'formatter' => "{b} : {d}%"))
  300. )
  301. ),
  302. cell
  303. (
  304. set::width('50%'),
  305. h::table
  306. (
  307. set::className('table'),
  308. h::tr
  309. (
  310. h::th($lang->report->item),
  311. h::th(set::width('100px'), $lang->report->value),
  312. h::th(set::width('120px'), $lang->report->percent)
  313. ),
  314. $tableTR
  315. )
  316. )
  317. )
  318. );
  319. }
  320. $mainActions = array();
  321. $canBeChanged = common::canBeChanged('testreport', $report);
  322. if($canBeChanged && hasPriv('testreport', 'create')) $mainActions[] = array('icon' => 'refresh', 'hint' => $lang->testreport->recreate, 'data-app' => $app->tab, 'url' => inlink('create', "objectID={$report->objectID}&objectType={$report->objectType}" . ($report->objectType == 'execution' || $report->objectType == 'project' ? "&extra=$report->tasks" : '')));
  323. if($canBeChanged && hasPriv('testreport', 'edit')) $mainActions[] = array('icon' => 'edit', 'hint' => $lang->testreport->edit, 'data-app' => $app->tab, 'url' => inlink('edit', "objectID={$report->id}"));
  324. if($canBeChanged && hasPriv('testreport', 'delete')) $mainActions[] = array('icon' => 'trash', 'hint' => $lang->testreport->delete, 'url' => inlink('delete', "objectID={$report->id}"), 'className' => 'ajax-submit', 'data-confirm' => $lang->testreport->confirmDelete, 'url' => inlink('delete', "objectID={$report->id}"));
  325. detailBody
  326. (
  327. sectionList
  328. (
  329. set::className('col gap-1 grow'),
  330. tabs
  331. (
  332. on::show('.tab-pane')->call('handleTabChange', jsRaw('event')),
  333. tabPane
  334. (
  335. set::key('basic'),
  336. to::divider(true),
  337. set::title($lang->testreport->view),
  338. set::active(true),
  339. sectionList
  340. (
  341. setClass('border rounded mb-4'),
  342. section
  343. (
  344. setClass('px-4'),
  345. set::title($lang->testreport->legendBasic),
  346. set::useHtml(true),
  347. tableData(item(set::name($lang->testreport->startEnd), $report->begin . ' ~ ' . $report->end), item(set::name($lang->testreport->owner), zget($users, $report->owner)), item(set::name($lang->testreport->members), $members), !empty($execution->desc) ? item
  348. (
  349. set::name($lang->testreport->goal),
  350. icon
  351. (
  352. 'help',
  353. setClass('text-light mr-0.5'),
  354. setData(array('toggle' => 'tooltip', 'title' => $lang->testreport->goalTip))
  355. ),
  356. strip_tags($execution->desc)
  357. ) : null, item
  358. (
  359. set::name($lang->testreport->profile),
  360. div
  361. (
  362. div(html($storySummary)),
  363. div(html(sprintf($lang->testreport->buildSummary, empty($builds) ? 1 : count($builds)) . $caseSummary)),
  364. div(html(sprintf($lang->testreport->bugSummary, $bugSummary['foundBugs'], count($legacyBugs), $bugSummary['activatedBugs'], $bugSummary['countBugByTask'], $bugSummary['bugConfirmedRate'] . '%', $bugSummary['bugCreateByCaseRate'] . '%')))
  365. )
  366. ), item(set::name($lang->testreport->legendComment), empty($report->report) ? $lang->testreport->none : html($report->report)))
  367. ),
  368. $report->files ? section
  369. (
  370. setClass('px-4'),
  371. set::title($lang->files),
  372. fileList
  373. (
  374. set::files($report->files),
  375. set::fieldset(false)
  376. )
  377. ) : null
  378. ),
  379. $this->session->notHead ? null : history(set::objectID($report->id))
  380. ),
  381. tabPane
  382. (
  383. set::key('storyAndBug'),
  384. to::prefix(icon('search')),
  385. set::title($lang->testreport->legendStoryAndBug),
  386. sectionList
  387. (
  388. dtable
  389. (
  390. set::cols($config->testreport->story->dtable->fieldList),
  391. set::data(array_values($stories)),
  392. set::emptyTip($lang->story->noStory),
  393. set::userMap($users)
  394. ),
  395. div(set::className('my-6')),
  396. dtable
  397. (
  398. set::cols($config->testreport->bug->dtable->fieldList),
  399. set::data(array_values($bugs)),
  400. set::emptyTip($lang->bug->notice->noBug),
  401. set::userMap($users)
  402. )
  403. )
  404. ),
  405. tabPane
  406. (
  407. set::key('tabBuild'),
  408. to::prefix(icon('search')),
  409. set::title($lang->testreport->legendBuild),
  410. sectionList
  411. (
  412. dtable
  413. (
  414. set::cols($config->testreport->build->dtable->fieldList),
  415. set::data(array_values($builds)),
  416. set::userMap($users)
  417. )
  418. )
  419. ),
  420. tabPane
  421. (
  422. set::key('tabCase'),
  423. to::prefix(icon('sitemap')),
  424. set::title($lang->testreport->legendCase),
  425. sectionList
  426. (
  427. dtable
  428. (
  429. set::cols($config->testreport->testcase->dtable->fieldList),
  430. set::data(array_values($caseList)),
  431. set::userMap($users)
  432. )
  433. )
  434. ),
  435. tabPane
  436. (
  437. set::key('tabLegacyBugs'),
  438. to::prefix(icon('bug')),
  439. to::divider(true),
  440. set::title($lang->testreport->legendLegacyBugs),
  441. sectionList
  442. (
  443. dtable
  444. (
  445. set::cols($config->testreport->bug->dtable->fieldList),
  446. set::data(array_values($legacyBugs)),
  447. set::userMap($users)
  448. )
  449. )
  450. ),
  451. tabPane
  452. (
  453. set::key('tabReport'),
  454. to::divider(true),
  455. set::title($lang->testreport->legendReport),
  456. $caseCharts,
  457. $bugStageChart,
  458. $bugHandleChart,
  459. $bugCharts
  460. ),
  461. $this->session->notHead ? null : tabPane
  462. (
  463. set::key('legendMore'),
  464. set::title($lang->testreport->legendMore),
  465. sectionList
  466. (
  467. span(html($lang->testreport->moreNotice))
  468. )
  469. )
  470. )
  471. ),
  472. $this->session->notHead ? null : floatToolbar
  473. (
  474. set::object($report),
  475. isAjaxRequest('modal') ? null : to::prefix(backBtn(set::icon('back'), setClass('ghost text-white'), $lang->goback)),
  476. !$report->deleted ? set::main($mainActions) : null
  477. )
  478. );
  479. $this->session->notHead ? render('fragment') : render();