annualdata.html.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. <?php include '../../common/view/header.lite.html.php';?>
  2. <?php include '../../common/view/chosen.html.php';?>
  3. <?php js::import($jsRoot . 'echarts/echarts.common.min.js'); ?>
  4. <?php js::import($jsRoot . 'echarts/timeline.min.js'); ?>
  5. <?php js::import($jsRoot . 'html2canvas/min.js'); ?>
  6. <?php $annualDataLang = $lang->report->annualData;?>
  7. <?php $annualDataConfig = $config->report->annualData;?>
  8. <?php $soFar = sprintf($annualDataLang->soFar, $year);?>
  9. <?php js::set('contributionGroups', $contributionGroups); ?>
  10. <div id='container' style='background-image: url(<?php echo $config->webRoot . 'theme/default/images/main/annual_data_bg.png'?>)'>
  11. <main id='main' style='background: url(<?php echo $config->webRoot . 'theme/default/images/main/annual_layout_header.png'?>) top no-repeat'>
  12. <header id='header'>
  13. <h1 class='text-holder' data-id='title'><?php echo $title;?></h1>
  14. </header>
  15. <div id='toolbar'>
  16. <div class='pull-left'>
  17. <span><?php echo $annualDataLang->scope;?></span>
  18. <?php echo html::select('year', $years, $year, "class='form-control'");?>
  19. <?php echo html::select('dept', $depts, $dept, "class='form-control chosen'");?>
  20. <?php echo html::select('account', $users, $account, "class='form-control chosen'");?>
  21. </div>
  22. <div class='pull-right'>
  23. <button type='button' class='btn btn-primary' id='exportBtn' title='<?php echo $lang->export;?>'><i class='icon icon-export'></i></button>
  24. <a id='imageDownloadBtn' class='hidden' download='annual_data.png'></a>
  25. </div>
  26. </div>
  27. <section id='baseInfo'>
  28. <header>
  29. <h2 class='text-holder'><?php echo $annualDataLang->baseInfo . $soFar;?></h2>
  30. <div class='report-tip'><icon class='icon icon-help' data-toggle='popover' data-html=true data-trigger='focus hover' data-placement='right' data-tip-class='text-muted popover-sm' data-content="<?php echo $lang->report->tips->basic[$mode];?>"></icon></div>
  31. </header>
  32. <div>
  33. <ul id='infoList'>
  34. <li>
  35. <?php echo $account ? $annualDataLang->logins : ((int)$dept ? $annualDataLang->deptUsers : $annualDataLang->companyUsers);?>
  36. <strong><?php echo $account ? $data['logins'] : $data['users'];?></strong>
  37. </li>
  38. <li>
  39. <?php echo $annualDataLang->actions;?>
  40. <strong><?php echo $data['actions'];?></strong>
  41. </li>
  42. <li>
  43. <?php echo $annualDataLang->consumed;?>
  44. <strong><?php echo $data['consumed'];?></strong>
  45. </li>
  46. <li class='dropdown dropdown-hover'>
  47. <?php echo $annualDataLang->todos;?>
  48. <strong><?php echo $data['todos']->count;?></strong>
  49. <ul class='dropdown-menu pull-right'>
  50. <li><?php echo $annualDataLang->todos;?></li>
  51. <li><span class='todoStatus'><?php echo $annualDataLang->todoStatus['all'];?></span><span><?php echo (int)$data['todos']->count;?></span></li>
  52. <li><span class='todoStatus'><?php echo $annualDataLang->todoStatus['undone'];?></span><span><?php echo (int)$data['todos']->undone;?></span></li>
  53. <li><span class='todoStatus'><?php echo $annualDataLang->todoStatus['done'];?></span><span><?php echo (int)$data['todos']->done;?></span></li>
  54. </ul>
  55. </li>
  56. <?php if($dept !== '' or !empty($account)):?>
  57. <li>
  58. <?php echo $annualDataLang->contributions;?>
  59. <div class='report-tip contribution-tip'><icon class='icon icon-help' data-toggle='popover' data-html=true data-trigger='focus hover' data-tip-class='text-muted' data-content="<?php echo $contributionCountTips;?>"></icon></div>
  60. <strong><?php echo $contributionCount;?></strong>
  61. </li>
  62. <?php endif;?>
  63. </ul>
  64. </div>
  65. </section>
  66. <section id='actionData'>
  67. <header>
  68. <h2 class='text-holder'><?php echo $annualDataLang->actionData . $soFar;?></h2>
  69. <div class='report-tip'><icon class='icon icon-help' data-toggle='popover' data-html=true data-trigger='focus hover' data-placement='right' data-tip-class='text-muted popover-sm' data-content="<?php echo $lang->report->tips->contribute[$mode];?>"></icon></div>
  70. </header>
  71. <div>
  72. <ul class='contributeActionList'>
  73. <?php foreach($annualDataLang->objectTypeList as $objectType => $objectName):?>
  74. <li class='dropdown dropdown-hover'>
  75. <span class='name'><?php echo $objectName;?></span>
  76. <span class='ratio'>
  77. <?php
  78. $objectContributions = isset($data['contributions'][$objectType]) ? $data['contributions'][$objectType] : array();
  79. $contributionActions = zget($annualDataConfig['contributions'], $objectType, array_keys($objectContributions));
  80. $colors = $annualDataConfig['colors'];
  81. $detail = '';
  82. $items = array();
  83. $maxWidth = 0;
  84. $maxWidthColor = '';
  85. $allPercent = 0;
  86. foreach($contributionActions as $actionName)
  87. {
  88. if($maxCount == 0) continue;
  89. if(isset($objectContributions[$actionName]))
  90. {
  91. $color = array_shift($colors);
  92. $count = $objectContributions[$actionName];
  93. if($count == 0) continue;
  94. $width = floor($count / $maxCount * 100);
  95. if($width == 0) $width = 1;
  96. $length = strlen($count);
  97. if($width < $annualDataConfig['itemMinWidth'][$length]) $width = $annualDataConfig['itemMinWidth'][$length];
  98. $allPercent += $width;
  99. if($maxWidth < $width)
  100. {
  101. $maxWidth = $width;
  102. $maxWidthColor = $color;
  103. }
  104. $item['color'] = $color;
  105. $item['width'] = $width;
  106. $item['count'] = $count;
  107. $items[$color] = $item;
  108. $detail .= "<li><span class='color' style='background-color:{$color}'></span><span class='item-name'>" . $annualDataLang->actionList[$actionName] . "</span><span class='count'>{$count}</span></li>";
  109. }
  110. }
  111. if($allPercent > 100) $items[$maxWidthColor]['width'] = $items[$maxWidthColor]['width'] - ($allPercent - 100);
  112. if($detail) $detail = "<li><span class='header'>{$objectName}</span></li>" . $detail;
  113. foreach($items as $item) echo "<span class='item' style='background-color:{$item['color']};width:{$item['width']}%'>{$item['count']}</span>";
  114. ?>
  115. </span>
  116. <?php if($detail):?>
  117. <ul class='dropdown-menu'><?php echo $detail;?></ul>
  118. <?php endif;?>
  119. </li>
  120. <?php endforeach;?>
  121. </ul>
  122. </div>
  123. </section>
  124. <section id='radar'>
  125. <header>
  126. <h2 class='text-holder'><?php echo $annualDataLang->radar . $soFar;?></h2>
  127. <div class='report-tip'><icon class='icon icon-help' data-toggle='popover' data-html=true data-trigger='focus hover' data-placement='left' data-tip-class='text-muted popover-sm' data-content="<?php echo $lang->report->tips->radar;?>"></icon></div>
  128. </header>
  129. <div id='radarCanvas'></div>
  130. </section>
  131. <section id='executionData'>
  132. <header>
  133. <h2 class='text-holder'><?php echo $annualDataLang->executions . $soFar;?></h2>
  134. <div class='report-tip'><icon class='icon icon-help' data-toggle='popover' data-html=true data-trigger='focus hover' data-placement='right' data-tip-class='text-muted popover-sm' data-content="<?php echo str_replace('{year}', $year, $lang->report->tips->execution[$mode]);?>"></icon></div>
  135. </header>
  136. <div class='has-table'>
  137. <table class='table table-hover table-fixed table-borderless table-condensed'>
  138. <thead class='hidden'>
  139. <tr>
  140. <?php foreach($annualDataLang->executionFields as $field => $name):?>
  141. <th class='<?php echo "c-$field";?>'><?php echo $name;?></th>
  142. <?php endforeach?>
  143. </tr>
  144. </thead>
  145. <tbody>
  146. <?php foreach($data['executionStat'] as $execution):?>
  147. <tr>
  148. <?php foreach($annualDataLang->executionFields as $field => $name):?>
  149. <td class='<?php echo "c-$field";?>' title='<?php echo $execution->$field;?>'><?php echo $execution->$field;?></td>
  150. <?php endforeach?>
  151. </tr>
  152. <?php endforeach;?>
  153. </tbody>
  154. </table>
  155. </div>
  156. <div class='table-header-fixed'>
  157. <table class='table table-hover table-fixed table-borderless table-condensed'>
  158. <thead>
  159. <tr>
  160. <?php foreach($annualDataLang->executionFields as $field => $name):?>
  161. <th class='<?php echo "c-$field";?>'><?php echo $name;?></th>
  162. <?php endforeach?>
  163. </tr>
  164. </thead>
  165. </table>
  166. </div>
  167. </section>
  168. <section id='productData'>
  169. <header>
  170. <h2 class='text-holder'><?php echo $annualDataLang->products . $soFar;?></h2>
  171. <div class='report-tip'><icon class='icon icon-help' data-toggle='popover' data-html=true data-trigger='focus hover' data-placement='right' data-tip-class='text-muted popover-sm' data-content="<?php echo $lang->report->tips->product[$mode];?>"></icon></div>
  172. </header>
  173. <div class='has-table'>
  174. <table class='table table-fixed table-hover table-borderless table-condensed'>
  175. <thead class='hidden'>
  176. <tr>
  177. <?php foreach($annualDataLang->productFields as $field => $name):?>
  178. <th class='<?php echo "c-$field";?>'><?php echo $name;?></th>
  179. <?php endforeach?>
  180. </tr>
  181. </thead>
  182. <tbody>
  183. <?php foreach($data['productStat'] as $product):?>
  184. <tr>
  185. <?php foreach($annualDataLang->productFields as $field => $name):?>
  186. <td class='<?php echo "c-$field";?>' title='<?php echo $product->$field;?>'><?php echo $product->$field;?></td>
  187. <?php endforeach?>
  188. </tr>
  189. <?php endforeach;?>
  190. </tbody>
  191. </table>
  192. </div>
  193. <div class='table-header-fixed'>
  194. <table class='table table-hover table-fixed table-borderless table-condensed'>
  195. <thead>
  196. <tr>
  197. <?php foreach($annualDataLang->productFields as $field => $name):?>
  198. <th class='<?php echo "c-$field";?>'><?php echo $name;?></th>
  199. <?php endforeach?>
  200. </tr>
  201. </thead>
  202. </table>
  203. </div>
  204. <div class='table-header-fixed'>
  205. </section>
  206. <?php if($dept === '' and empty($account)):?>
  207. <section id='allTimeStatusStat'>
  208. <header><h2 class='text-holder'><?php echo $annualDataLang->statusStat;?></h2></header>
  209. <div>
  210. <div class='canvas' id='allStoryStatusCanvas'></div>
  211. <div class='canvas' id='allTaskStatusCanvas'></div>
  212. <div class='canvas' id='allBugStatusCanvas'></div>
  213. <?php
  214. foreach($data['statusStat'] as $objectType => $objectStatusStat):?>
  215. <div class='<?php echo $objectType;?>Overview hidden'><?php echo $this->report->getStatusOverview($objectType, $objectStatusStat);?></div>
  216. <?php endforeach;?>
  217. </div>
  218. </section>
  219. <?php endif;?>
  220. <?php
  221. $objectTypeList['story'] = $radarData['product'];
  222. $objectTypeList['task'] = $radarData['execution'] > $radarData['devel'] ? $radarData['execution'] : $radarData['devel'];
  223. $objectTypeList['bug'] = $radarData['qa'];
  224. $objectTypeList['case'] = $radarData['qa'];
  225. arsort($objectTypeList);
  226. ?>
  227. <?php foreach(array_keys($objectTypeList) as $objectType):?>
  228. <section class='dataYearStat' id='<?php echo $objectType;?>Data'>
  229. <?php if($objectType == 'story') $sectionHeader = $annualDataLang->stories;?>
  230. <?php if($objectType == 'task') $sectionHeader = $annualDataLang->tasks;?>
  231. <?php if($objectType == 'bug') $sectionHeader = $annualDataLang->bugs;?>
  232. <?php if($objectType == 'case') $sectionHeader = $annualDataLang->cases;?>
  233. <?php $ucfirst = ucfirst($objectType);?>
  234. <header>
  235. <h2 class='text-holder'><?php echo $sectionHeader . $soFar;?></h2>
  236. <div class='report-tip'><icon class='icon icon-help' data-toggle='popover' data-html=true data-trigger='focus hover' data-placement='right' data-tip-class='text-muted popover-sm' data-content="<?php echo $lang->report->tips->$objectType[$mode];?>"></icon></div>
  237. </header>
  238. <div>
  239. <div class='canvas left' id='<?php echo $objectType == 'case' ? "yearCaseResultCanvas" : "year{$ucfirst}StatusCanvas";?>'></div>
  240. <div class='canvas right' id='year<?php echo $ucfirst;?>ActionCanvas'></div>
  241. <?php if($objectType != 'case'):?>
  242. <div class='year<?php echo $ucfirst;?>Overview hidden'><?php echo $this->report->getStatusOverview($objectType, $data["{$objectType}Stat"]['statusStat']);?></div>
  243. <?php endif;?>
  244. </div>
  245. </section>
  246. <?php endforeach;?>
  247. </main>
  248. <div id='loadIndicator' class='load-indicator'></div>
  249. </div>
  250. <?php js::set('exportByZentao', $annualDataLang->exportByZentao);?>
  251. <?php js::set('radarData1', $radarData); ?>
  252. <?php js::set('annualDataLang1', $annualDataLang); ?>
  253. <script>
  254. $(function()
  255. {
  256. <?php
  257. $indicator = array();
  258. foreach($annualDataLang->radarItems as $radarKey => $radarName)
  259. {
  260. $indicator[$radarKey]['name'] = $radarName;
  261. $indicator[$radarKey]['max'] = 0;
  262. }
  263. ?>
  264. var indicator = <?php echo json_encode(array_values($indicator));?>;
  265. var contributionData = [];
  266. var yearsData = [];
  267. if(contributionGroups) {
  268. for(var contributionKey in contributionGroups)
  269. {
  270. yearsData.push(contributionKey);
  271. var itemData = [];
  272. var newIndicator = [];
  273. for(var itemKey in contributionGroups[contributionKey])
  274. {
  275. itemData.push(contributionGroups[contributionKey][itemKey]);
  276. }
  277. itemMax = Math.max.apply(null,itemData);
  278. var resultIndicator = indicator.map(function(item,index)
  279. {
  280. item.max = itemMax;
  281. return {...item};
  282. })
  283. var contributionItem = {
  284. year: contributionKey,
  285. data: itemData || [],
  286. max: itemMax,
  287. indicator: resultIndicator,
  288. }
  289. contributionData.push(contributionItem);
  290. }
  291. }
  292. contributionData.sort(function(a,b)
  293. {
  294. if(a.year === "<?php echo $year;?>")
  295. {
  296. return 1;
  297. }
  298. else if(b.year === "<?php echo $year;?>")
  299. {
  300. return -1;
  301. }
  302. else
  303. {
  304. return 0;
  305. }
  306. });
  307. var radarChart = echarts.init(document.getElementById('radarCanvas'));
  308. var radarIndicatorData = [];
  309. for(var k = 0; k < contributionData.length; k++)
  310. {
  311. optionsItem = {
  312. 'radarIndicator': contributionData[k].indicator,
  313. 'tradeRange': contributionData[k].data,
  314. }
  315. radarIndicatorData.push(optionsItem);
  316. }
  317. var radarOption = {
  318. baseOption: {
  319. title: {},
  320. timeline: {
  321. show: yearsData.length && yearsData.length > 1,
  322. axisType: 'category',
  323. autoPlay: false,
  324. loop: true,
  325. playInterval: 1000,
  326. left: "1%",
  327. bottom: "1%",
  328. width: '90%',
  329. data: yearsData,
  330. currentIndex: yearsData.length - 1,
  331. symbolSize: [5, 5],
  332. label: {
  333. fontSize: 10,
  334. lineHeight: 18,
  335. interval: 'auto',
  336. },
  337. emphasis: {
  338. label: {
  339. fontSize: 10,
  340. },
  341. },
  342. progress: {
  343. label: {
  344. fontSize: 10,
  345. },
  346. },
  347. lineStyle: {
  348. width: 5,
  349. },
  350. controlStyle: {
  351. itemSize: 18,
  352. },
  353. },
  354. tooltip: {},
  355. series: [{
  356. name:'<?php echo $annualDataLang->radar;?>',
  357. areaStyle:{color: 'rgb(45, 40, 33)'},
  358. type: 'radar',
  359. itemStyle: {color: "#fff", borderColor:"rgb(247, 193, 35)"},
  360. lineStyle: {color: "rgb(247, 193, 35)"},
  361. }]
  362. },
  363. options: []
  364. };
  365. var newOptions = [];
  366. for(var k = 0; k < radarIndicatorData.length; k++)
  367. {
  368. optionsItem = {
  369. radar: {
  370. splitNumber: 5,
  371. radius: 88,
  372. indicator: radarIndicatorData[k].radarIndicator
  373. },
  374. series: [{
  375. data: [{
  376. value: radarIndicatorData[k].tradeRange
  377. }]
  378. }]
  379. }
  380. newOptions.push(optionsItem);
  381. }
  382. radarOption.options = (radarOption.options).concat(newOptions);
  383. radarChart.setOption(radarOption);
  384. var overviewCSS = {position: 'absolute', left: '172px', top: '160px'};
  385. <?php unset($lang->story->statusList['']);?>
  386. <?php unset($lang->bug->statusList['']);?>
  387. <?php unset($lang->task->statusList['']);?>
  388. <?php if($dept === '' and empty($account)):?>
  389. <?php foreach($data['statusStat'] as $objectType => $objectStatusStat):?>
  390. <?php
  391. $statusStat = array();
  392. foreach($lang->$objectType->statusList as $status => $statusName)
  393. {
  394. $statusCount = zget($objectStatusStat, $status, 0);
  395. if($statusCount == 0) continue;
  396. $statusStat[$status] = array('name' => $statusName, 'value' => $statusCount);
  397. }
  398. $canvasID = 'all' . ucfirst($objectType) . 'StatusCanvas';
  399. $canvasTitleKey = $objectType . 'StatusStat';
  400. $jsonedStatusStat = json_encode(array_values($statusStat));
  401. echo "drawStatusPieChart('{$canvasID}', '{$annualDataLang->$canvasTitleKey}', $jsonedStatusStat,
  402. function()
  403. {
  404. $('#allTimeStatusStat .{$objectType}Overview').appendTo('#{$canvasID}').removeClass('hidden').css(overviewCSS)
  405. });\n";
  406. ?>
  407. <?php endforeach;?>
  408. <?php endif;?>
  409. var yearOverviewCSS = {position: 'absolute', left: '200px', top: '160px'};
  410. <?php foreach(array('story', 'task', 'bug', 'case') as $objectType):?>
  411. <?php
  412. $stat = array();
  413. $items = $objectType == 'case' ? $lang->testcase->resultList : $lang->$objectType->statusList;
  414. $statKey = $objectType == 'case' ? 'resultStat' : 'statusStat';
  415. foreach($items as $key => $name)
  416. {
  417. $itemCount = zget($data["{$objectType}Stat"][$statKey], $key, 0);
  418. if($itemCount == 0) continue;
  419. $stat[$key] = array('name' => $name, 'value' => $itemCount);
  420. }
  421. $ucfirst = ucfirst($objectType);
  422. $canvasID = $objectType == 'case' ? 'yearCaseResultCanvas' : 'year' . $ucfirst . 'StatusCanvas';
  423. $canvasTitleKey = $objectType == 'case' ? 'caseResultStat' : $objectType . 'StatusStat';
  424. $jsonedStat = json_encode(array_values($stat));
  425. $drawFunction = "drawStatusPieChart('{$canvasID}', '{$annualDataLang->$canvasTitleKey}', $jsonedStat";
  426. if($objectType != 'case')
  427. {
  428. $drawFunction .= ", function()
  429. {
  430. $('#{$objectType}Data .year{$ucfirst}Overview').appendTo('#{$canvasID}').removeClass('hidden').css(yearOverviewCSS)
  431. }";
  432. }
  433. $drawFunction .= ");\n";
  434. echo $drawFunction;
  435. ?>
  436. <?php endforeach;?>
  437. <?php
  438. $commonTemplate['name'] = '';
  439. $commonTemplate['type'] = 'bar';
  440. $commonTemplate['stack'] = 'all';
  441. $commonTemplate['label'] = array('show' => false);
  442. $commonTemplate['data'] = array();
  443. $jsonedMonths = json_encode($months);
  444. foreach($annualDataConfig['month'] as $objectType => $actions):?>
  445. <?php
  446. $legends = array();
  447. $monthActions = array();
  448. $allCount = 0;
  449. foreach($actions as $actionKey => $action)
  450. {
  451. if(!isset($data["{$objectType}Stat"]['actionStat'][$actionKey])) continue;
  452. $actionName = $annualDataLang->actionList[$action];
  453. $legends[] = $actionName;
  454. $monthAction = $commonTemplate;
  455. $monthAction['name'] = $actionName;
  456. $monthAction['stack'] = $objectType;
  457. $monthAction['data'] = array_values($data["{$objectType}Stat"]['actionStat'][$actionKey]);
  458. $monthActions[] = $monthAction;
  459. $allCount += array_sum($monthAction['data']);
  460. }
  461. if($allCount == 0)
  462. {
  463. $monthActions = array();
  464. $legends = array();
  465. }
  466. $canvasID = 'year' . ucfirst($objectType) . 'ActionCanvas';
  467. $canvasTitleKey = $objectType . 'MonthActions';
  468. $legends = json_encode($legends);
  469. $monthActions = json_encode($monthActions);
  470. echo "drawMonthsBarChart('{$canvasID}', '{$annualDataLang->$canvasTitleKey}', {$legends}, {$jsonedMonths}, {$monthActions});\n";
  471. ?>
  472. <?php endforeach;?>
  473. })
  474. </script>
  475. <?php include '../../common/view/footer.lite.html.php';?>