grouptask.html.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. <?php
  2. /**
  3. * The group task view file of execution 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 Sun Guangming<sunguangming@easycorp.ltd>
  7. * @package execution
  8. * @link https://www.zentao.net
  9. */
  10. namespace zin;
  11. include 'header.html.php';
  12. $items = array();
  13. if(isset($lang->execution->groupFilter[$groupBy]))
  14. {
  15. foreach($lang->execution->groupFilter[$groupBy] as $filterKey => $name)
  16. {
  17. $items[] = li
  18. (
  19. setClass('nav-item'),
  20. a
  21. (
  22. ($filterKey == $filter) ? set('class', 'active') : null,
  23. span(setClass('text'), $name),
  24. ($filterKey == $filter) ? span(setClass('label size-sm rounded-full white'), $allCount) : null,
  25. set::href(createLink('execution', 'grouptask', "executionID={$executionID}&groupBy={$groupBy}&filter={$filterKey}"))
  26. )
  27. );
  28. }
  29. }
  30. else
  31. {
  32. $items[] = li
  33. (
  34. setClass('nav-item'),
  35. a
  36. (
  37. set('class', 'active'),
  38. span(setClass('text'), $lang->all),
  39. span(setClass('label size-sm rounded-full white'), $allCount),
  40. set::href(createLink('execution', 'grouptask', "executionID={$executionID}&groupBy={$groupBy}"))
  41. )
  42. );
  43. }
  44. $lang->task->statusList['changed'] = $lang->task->storyChange;
  45. featureBar
  46. (
  47. li
  48. (
  49. setClass('nav-item feature-actions'),
  50. a
  51. (
  52. setClass('btn ghost group-collapse-all'),
  53. span(setClass('text'), $lang->execution->treeLevel['root']),
  54. icon('fold-all')
  55. )
  56. ),
  57. li
  58. (
  59. setClass('nav-item hidden feature-actions'),
  60. a
  61. (
  62. setClass('btn ghost group-expand-all'),
  63. span(setClass('text'), $lang->execution->treeLevel['all']),
  64. icon('unfold-all')
  65. )
  66. ),
  67. $items
  68. );
  69. $canCreate = hasPriv('task', 'create');
  70. $canImportTask = hasPriv('task', 'importTask');
  71. if(common::canModify('execution', $execution))
  72. {
  73. $createLink = $this->createLink('task', 'create', "executionID={$execution->id}");
  74. if(commonModel::isTutorialMode())
  75. {
  76. $wizardParams = helper::safe64Encode("executionID={$execution->id}");
  77. $taskCreateLink = $this->createLink('tutorial', 'wizard', "module=task&method=create&params=$wizardParams");
  78. }
  79. $createItem = array('text' => $lang->task->create, 'url' => $createLink);
  80. if($canImportTask && $execution->multiple) $importTaskItem = array('text' => $lang->execution->importTask, 'url' => $this->createLink('execution', 'importTask', "execution={$execution->id}"));
  81. }
  82. toolbar
  83. (
  84. hasPriv('task', 'report') ? item(set(array
  85. (
  86. 'class' => 'btn ghost',
  87. 'icon' => 'bar-chart',
  88. 'text' => $lang->task->report->common,
  89. 'url' => createLink('task', 'report', "execution={$execution->id}&browseType={$browseType}")
  90. ))) : null,
  91. hasPriv('task', 'export') ? item(set(array
  92. (
  93. 'class' => 'btn ghost',
  94. 'icon' => 'export',
  95. 'text' => $lang->export,
  96. 'url' => createLink('task', 'export', "execution={$execution->id}&orderBy={$orderBy}&type={$browseType}"),
  97. 'data-toggle' => 'modal'
  98. ))) : null,
  99. !empty($importTaskItem) ? dropdown(
  100. btn(
  101. setClass('btn ghost'),
  102. set::icon('import'),
  103. $lang->import
  104. ),
  105. set::items(array_filter(array($importTaskItem))),
  106. set::placement('bottom-end')
  107. ) : null,
  108. $canCreate ? item(set($createItem + array('class' => 'btn primary', 'icon' => 'plus'))) : null
  109. );
  110. $groupList = array();
  111. foreach($lang->execution->groups as $key => $value)
  112. {
  113. $link = createLink('execution', 'grouptask', "executionID={$executionID}&groupBy={$key}");
  114. $groupList[] = array(
  115. 'text' => $value,
  116. 'url' => $link
  117. );
  118. }
  119. $thead = function() use($lang, $groupList, $groupBy, $allCount)
  120. {
  121. return h::tr
  122. (
  123. $allCount ? setClass('border-divider') : null,
  124. h::th
  125. (
  126. setClass('c-side text-left has-btn group-menu'),
  127. dropdown
  128. (
  129. btn
  130. (
  131. setClass('ghost btn square btn-default'),
  132. $lang->execution->groups[$groupBy]
  133. ),
  134. set::items($groupList)
  135. )
  136. ),
  137. h::th
  138. (
  139. setClass('c-id'),
  140. $lang->task->id
  141. ),
  142. h::th
  143. (
  144. setClass('c-pri'),
  145. $lang->priAB
  146. ),
  147. h::th
  148. (
  149. setClass('c-name'),
  150. $lang->task->name
  151. ),
  152. h::th
  153. (
  154. setClass('c-status'),
  155. $lang->task->status
  156. ),
  157. h::th
  158. (
  159. setClass('c-user'),
  160. $lang->task->assignedTo
  161. ),
  162. h::th
  163. (
  164. setClass('c-user'),
  165. $lang->task->finishedBy
  166. ),
  167. h::th
  168. (
  169. setClass('c-hours'),
  170. $lang->task->estimateAB
  171. ),
  172. h::th
  173. (
  174. setClass('c-hours'),
  175. $lang->task->consumedAB
  176. ),
  177. h::th
  178. (
  179. setClass('c-hours'),
  180. $lang->task->leftAB
  181. ),
  182. h::th
  183. (
  184. setClass('c-progress'),
  185. $lang->task->progressAB
  186. ),
  187. h::th
  188. (
  189. setClass('c-type'),
  190. $lang->typeAB
  191. ),
  192. h::th
  193. (
  194. setClass('c-date'),
  195. $lang->task->deadline
  196. ),
  197. h::th
  198. (
  199. setClass('c-actions'),
  200. $lang->actions
  201. )
  202. );
  203. };
  204. $tbody = function() use($tasks, $lang, $groupBy, $users, $groupByList, $execution)
  205. {
  206. global $app;
  207. $tbody = array();
  208. $groupIndex = 1;
  209. foreach($tasks as $groupKey => $groupTasks)
  210. {
  211. $groupWait = 0;
  212. $groupDone = 0;
  213. $groupDoing = 0;
  214. $groupClosed = 0;
  215. $groupEstimate = 0.0;
  216. $groupConsumed = 0.0;
  217. $groupLeft = 0.0;
  218. $groupName = $groupKey;
  219. if($groupBy == 'story') $groupName = empty($groupName) ? $lang->task->noStory : zget($groupByList, $groupKey);
  220. if($groupBy == 'assignedTo' and $groupName == '') $groupName = $this->lang->task->noAssigned;
  221. $groupSum = 0;
  222. foreach($groupTasks as $taskKey => $task)
  223. {
  224. if($groupBy == 'story')
  225. {
  226. if($task->parent >= 0)
  227. {
  228. $groupEstimate += $task->estimate;
  229. $groupConsumed += $task->consumed;
  230. if($task->status != 'cancel' && $task->status != 'closed') $groupLeft += $task->left;
  231. }
  232. }
  233. else
  234. {
  235. if($task->parent >= 0)
  236. {
  237. $groupEstimate += $task->estimate;
  238. $groupConsumed += $task->consumed;
  239. if($groupBy == 'status' || ($task->status != 'cancel' && $task->status != 'closed')) $groupLeft += $task->left;
  240. }
  241. }
  242. if($task->status == 'wait') $groupWait++;
  243. if($task->status == 'doing') $groupDoing++;
  244. if($task->status == 'done') $groupDone++;
  245. if($task->status == 'closed') $groupClosed++;
  246. }
  247. $groupSum = count($groupTasks);
  248. $i = 0;
  249. foreach($groupTasks as $task)
  250. {
  251. $assignedToStyle = $task->assignedTo == $app->user->account ? "style='color:red'" : '';
  252. $tbody[] = h::tr
  253. (
  254. set(array('data-id' => $groupIndex)),
  255. ($groupIndex > 1 and $i == 0) ? setClass('divider-top') : null,
  256. $i == 0 ? h::td
  257. (
  258. $groupSum > 4 ? setClass('c-side text-left group-toggle text-top c-side-lg') : setClass('c-side text-left group-toggle text-top'),
  259. set::rowspan($groupSum),
  260. div
  261. (
  262. setClass('group-header'),
  263. a
  264. (
  265. setClass('groupBtn'),
  266. set::href('###'),
  267. icon('caret-down'),
  268. $groupName
  269. ),
  270. div
  271. (
  272. setClass('groupSummary small'),
  273. ($groupBy == 'assignedTo' and isset($members[$task->assignedTo])) ? html(sprintf($lang->execution->memberHoursAB, zget($users, $task->assignedTo), $members[$task->assignedTo]->totalHours)) : null,
  274. html(sprintf($lang->execution->groupSummaryAB, $groupSum, $groupWait, $groupDoing, $groupEstimate . $lang->execution->workHourUnit, $groupConsumed . $lang->execution->workHourUnit, $groupLeft . $lang->execution->workHourUnit))
  275. )
  276. )
  277. ) : null,
  278. h::td(sprintf('%03d', (string)$task->id)),
  279. h::td
  280. (
  281. span
  282. (
  283. setClass("pri-{$task->pri}"),
  284. $task->pri
  285. )
  286. ),
  287. h::td
  288. (
  289. setClass('c-name'),
  290. set('title', $task->name),
  291. !empty($task->team) ? span(setClass('label gray-pale rounded-xl'), $lang->task->multipleAB) : null,
  292. $task->parent > 0 ? span(setClass('label gray-pale rounded-xl'), $lang->task->childrenAB) : null,
  293. (isset($task->children) && $task->children == true) ? span(setClass('label gray-pale rounded-xl'), $lang->task->parentAB) : null,
  294. a(set::href(createLink('task', 'view', "task=$task->id")), $task->name, setData(array('toggle' => 'modal', 'size' => 'lg')))
  295. ),
  296. h::td
  297. (
  298. setClass('text-center'),
  299. span
  300. (
  301. setClass("status-{$task->status}"),
  302. $lang->task->statusList[$task->status]
  303. )
  304. ),
  305. h::td
  306. (
  307. setClass('text-center'),
  308. span
  309. (
  310. set(array('style' => $assignedToStyle)),
  311. $task->assignedToRealName
  312. )
  313. ),
  314. h::td
  315. (
  316. setClass('text-center'),
  317. zget($users, $task->finishedBy)
  318. ),
  319. h::td
  320. (
  321. setClass('text-right'),
  322. $task->estimate . $lang->execution->workHourUnit
  323. ),
  324. h::td
  325. (
  326. setClass('text-right'),
  327. $task->consumed . $lang->execution->workHourUnit
  328. ),
  329. h::td
  330. (
  331. setClass('text-right'),
  332. $task->left . $lang->execution->workHourUnit
  333. ),
  334. h::td
  335. (
  336. setClass('text-right'),
  337. $task->progress . '%'
  338. ),
  339. h::td
  340. (
  341. setClass('text-center'),
  342. zget($lang->task->typeList, $task->type)
  343. ),
  344. h::td
  345. (
  346. setClass('text-center'),
  347. isset($task->delay) ? setClass('delayed') : null,
  348. (substr((string)$task->deadline, 0, 4) > 0) ? substr((string)$task->deadline, 5, 6) : null
  349. ),
  350. common::canModify('execution', $execution) ? h::td
  351. (
  352. setClass('text-center'),
  353. common::hasPriv('task', 'assignTo') ? btn
  354. (
  355. set
  356. (
  357. array
  358. (
  359. 'url' => createLink('task', 'assignTo', "executionID=$task->execution&taskID=$task->id"),
  360. 'data-toggle' => 'modal',
  361. 'class' => 'btn ghost toolbar-item text-primary square size-sm',
  362. 'icon' => 'hand-right'
  363. )
  364. )
  365. ) : null,
  366. common::hasPriv('task', 'edit') ? btn
  367. (
  368. set
  369. (
  370. array
  371. (
  372. 'url' => createLink('task', 'edit', "taskID=$task->id"),
  373. 'class' => 'btn ghost toolbar-item text-primary square size-sm',
  374. 'icon' => 'edit'
  375. )
  376. )
  377. ) : null,
  378. common::hasPriv('task', 'edit') ? btn
  379. (
  380. set
  381. (
  382. array
  383. (
  384. 'url' => createLink('task', 'delete', "taskID=$task->id"),
  385. 'data-confirm' => $lang->task->confirmDelete,
  386. 'class' => 'btn ghost toolbar-item text-primary square size-sm ajax-submit',
  387. 'icon' => 'trash'
  388. )
  389. )
  390. ) : null
  391. )
  392. : h::td()
  393. );
  394. $i ++;
  395. }
  396. if($i != 0)
  397. {
  398. $tbody[] = h::tr
  399. (
  400. $groupIndex > 1 ? setClass('hidden group-toggle group-summary divider-top') : setClass('hidden group-summary group-toggle'),
  401. set(array('data-id' => $groupIndex)),
  402. h::td
  403. (
  404. setClass('c-side'),
  405. div
  406. (
  407. setClass('summary-header'),
  408. a
  409. (
  410. setClass('summaryBtn'),
  411. set::href('###'),
  412. icon('caret-right'),
  413. $groupName
  414. )
  415. )
  416. ),
  417. h::td
  418. (
  419. set::colspan(13),
  420. div
  421. (
  422. setClass('table-row segments-list'),
  423. ($groupBy == 'assignedTo' and isset($members[$task->assignedTo])) ? html(sprintf($lang->execution->memberHours, zget($users, $task->assignedTo), $members[$task->assignedTo]->totalHours)) : null,
  424. ($groupBy == 'assignedTo' and $task->assignedTo and !isset($members[$task->assignedTo])) ? html(sprintf($lang->execution->memberHours, zget($users, $task->assignedTo), '0.0')) : null,
  425. ($groupBy == 'assignedTo' and empty($task->assignedTo)) ? div
  426. (
  427. setClass('table-col'),
  428. div
  429. (
  430. setClass('segments'),
  431. div
  432. (
  433. setClass('segment'),
  434. div
  435. (
  436. setClass('segment-title'),
  437. $groupName
  438. )
  439. )
  440. )
  441. ) : null,
  442. html(sprintf($lang->execution->countSummary, $groupSum, $groupDoing, $groupWait)),
  443. html(sprintf($lang->execution->timeSummary, $groupEstimate . $lang->execution->workHourUnit, $groupConsumed . $lang->execution->workHourUnit, $groupLeft . $lang->execution->workHourUnit))
  444. )
  445. )
  446. );
  447. }
  448. $groupIndex ++;
  449. }
  450. return $tbody;
  451. };
  452. if($tasks)
  453. {
  454. div
  455. (
  456. set::id('tasksTable'),
  457. h::table
  458. (
  459. setClass('table condensed'),
  460. h::thead($thead()),
  461. h::tbody($tbody())
  462. )
  463. );
  464. }
  465. else
  466. {
  467. div
  468. (
  469. setClass('canvas text-center py-8'),
  470. $lang->task->noTask
  471. );
  472. }