browsebycard.html.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. <?php
  2. /**
  3. * The browsebycard view file of project 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 Shujie Tian<tianshujie@easycorp.ltd>
  7. * @package project
  8. * @link https://www.zentao.net
  9. */
  10. namespace zin;
  11. jsVar('browseType', $browseType);
  12. jsVar('param', $param);
  13. jsVar('recTotal', $pager->recTotal);
  14. jsVar('recPerPage', $pager->recPerPage);
  15. jsVar('pageID', $pager->pageID);
  16. /* zin: Define the feature bar on main menu. */
  17. unset($programs[0]);
  18. featureBar
  19. (
  20. helper::hasFeature('program') ? to::before
  21. (
  22. div
  23. (
  24. picker
  25. (
  26. set::name('programID'),
  27. set::value($programID),
  28. set::items($programs),
  29. set::width('200px'),
  30. set::placeholder($lang->project->selectProgram),
  31. on::change('changeProgram')
  32. )
  33. )
  34. ) : null,
  35. set::current($browseType),
  36. set::linkParams("programID={$programID}&status={key}&param=&orderBy={$orderBy}&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}"),
  37. checkbox
  38. (
  39. set::rootClass('mx-2'),
  40. set::name('involved'),
  41. set::text($lang->project->mine),
  42. set::checked($this->cookie->involved ? 'checked' : '')
  43. ),
  44. li(searchToggle(set::module('project'), set::open($browseType == 'bysearch')))
  45. );
  46. /* zin: Define the toolbar on main menu. */
  47. toolbar
  48. (
  49. item(set(array
  50. (
  51. 'type' => 'btnGroup',
  52. 'items' => array(array
  53. (
  54. 'icon' => 'list',
  55. 'class' => 'switchButton btn-icon',
  56. 'data-type' => 'bylist',
  57. 'hint' => $lang->project->bylist
  58. ), array
  59. (
  60. 'icon' => 'cards-view',
  61. 'class' => 'btn-icon switchButton text-primary',
  62. 'data-type' => 'bycard',
  63. 'hint' => $lang->project->bycard
  64. ))
  65. ))),
  66. hasPriv('project', 'export') ? item(set(array
  67. (
  68. 'icon' => 'export',
  69. 'text' => $lang->project->export,
  70. 'class' => 'ghost export',
  71. 'url' => createLink('project', 'export', "status={$browseType}&orderBy={$orderBy}"),
  72. 'data-toggle' => 'modal'
  73. ))) : null,
  74. hasPriv('project', 'create') ? item(set(array
  75. (
  76. 'icon' => 'plus',
  77. 'text' => $lang->project->create,
  78. 'class' => 'primary create-project-btn',
  79. 'url' => createLink('project', 'createGuide', "programID={$programID}"),
  80. 'data-toggle' => 'modal',
  81. 'data-position' => 'center'
  82. ))) : null
  83. );
  84. $projectCards = null;
  85. if(!empty($projectStats))
  86. {
  87. foreach($projectStats as $project)
  88. {
  89. $status = isset($project->delay) ? 'delay' : $project->status;
  90. $statusLabel = $config->project->statusLabelList[$status];
  91. $project->end = $project->end == LONG_TIME ? $this->lang->project->longTime : $project->end;
  92. $project->date = str_replace('-', '.', $project->begin) . ' - ' . str_replace('-', '.', $project->end);
  93. $count = 0;
  94. $memberAvatars = null;
  95. $lastMember = end($project->teamMembers);
  96. if(!empty($project->teamMembers))
  97. {
  98. foreach($project->teamMembers as $key => $member)
  99. {
  100. if(!isset($users[$member]))
  101. {
  102. $project->teamCount --;
  103. unset($project->teamMembers[$key]);
  104. continue;
  105. }
  106. if($count > 2) continue;
  107. $memberAvatars[] = div
  108. (
  109. setClass('avatar circle size-sm'),
  110. set::title($users[$member]),
  111. avatar
  112. (
  113. set::size('sm'),
  114. set::text($users[$member]),
  115. set::src(zget($usersAvatar, $member, ''))
  116. )
  117. );
  118. $count ++;
  119. }
  120. }
  121. $actionItems = array();
  122. $actionParams = "projectID={$project->id}";
  123. $actionList = array('edit', 'start', 'suspend', 'close', 'activate');
  124. foreach($actionList as $action)
  125. {
  126. if(!common::hasPriv('project', $action)) continue;
  127. $actionItem = $config->project->actionList[$action];
  128. if($this->project->isClickable($project, $action))
  129. {
  130. $actionItem['url'] = createLink('project', $action, $actionParams);
  131. $actionItem['className'] = 'text-primary';
  132. }
  133. else
  134. {
  135. unset($actionItem['url']);
  136. $actionItem['disabled'] = true;
  137. }
  138. $actionItems[] = $actionItem;
  139. }
  140. $projectCards[] = div
  141. (
  142. setClass('col'),
  143. set('data-id', $project->id),
  144. div
  145. (
  146. setClass('panel'),
  147. div
  148. (
  149. setClass('panel-heading'),
  150. span
  151. (
  152. setClass('label project-type-label'),
  153. setClass(in_array($project->model, array('waterfall', 'waterfallplus')) ? 'warning-pale ring-warning' : 'secondary-pale ring-secondary'),
  154. icon($project->model == 'scrum' ? 'sprint' : $project->model)
  155. ),
  156. a
  157. (
  158. setClass('project-name'),
  159. set::href(createLink('project', 'index', "projectID={$project->id}")),
  160. set::title($project->name),
  161. h::strong($project->name)
  162. ),
  163. span
  164. (
  165. setClass("project-status label rounded-full {$statusLabel}"),
  166. $status != 'delay' ? $lang->project->statusList[$status] : sprintf($lang->project->delayInfo, $project->delay)
  167. )
  168. ),
  169. div
  170. (
  171. setClass('panel-body'),
  172. div
  173. (
  174. setClass('project-infos'),
  175. span
  176. (
  177. set::title($project->budget),
  178. setClass('label gray-100'),
  179. $project->budget
  180. ),
  181. span
  182. (
  183. set::title($project->date),
  184. setClass('label gray-100 mr-2'),
  185. setStyle('color', $status == 'delay' ? 'var(--color-danger-500)' : 'inherit'),
  186. $project->date
  187. )
  188. ),
  189. div
  190. (
  191. setClass('project-detail pl-8 pt-2'),
  192. div
  193. (
  194. setClass('row'),
  195. div
  196. (
  197. setClass($app->getClientLang() == 'en' ? 'w-1/3' : 'w-1/4'),
  198. div
  199. (
  200. span
  201. (
  202. setClass('statistics-title'),
  203. $lang->projectCommon . $lang->project->progress
  204. )
  205. ),
  206. div
  207. (
  208. setClass('pl-4'),
  209. set('data-zui', 'ProgressCircle'),
  210. set('data-percent', $project->progress),
  211. set('data-size', 24),
  212. set('data-circle-color', 'var(--color-success-500)')
  213. )
  214. ),
  215. div
  216. (
  217. setClass('w-1/3 text-center'),
  218. span
  219. (
  220. setClass('statistics-title'),
  221. $lang->project->leftTasks
  222. ),
  223. span
  224. (
  225. setClass('leftTasks'),
  226. set::title($project->leftTasks),
  227. $project->leftTasks
  228. )
  229. ),
  230. div
  231. (
  232. setClass('w-1/3 text-center'),
  233. span
  234. (
  235. setClass('statistics-title'),
  236. $lang->project->leftHours
  237. ),
  238. span
  239. (
  240. setClass('totalLeft'),
  241. set::title(empty($project->left) ? '— ' : $project->left . 'h'),
  242. empty($project->left) ? '— ' : $project->left . 'h'
  243. )
  244. )
  245. )
  246. ),
  247. div
  248. (
  249. setClass('project-footer pt-2'),
  250. div
  251. (
  252. setClass('project-team'),
  253. div
  254. (
  255. setClass('project-members avatar-group gap-4'),
  256. $memberAvatars,
  257. $project->teamCount > 4 ? span
  258. (
  259. '…'
  260. ) : null,
  261. $project->teamCount > 3 ? div
  262. (
  263. setClass('avatar size-sm circle'),
  264. set::title($users[$lastMember]),
  265. avatar
  266. (
  267. set::size('sm'),
  268. set::text($users[$lastMember]),
  269. set::src(zget($usersAvatar, $lastMember, ''))
  270. )
  271. ) : null,
  272. a
  273. (
  274. setClass('project-members-total pl-2 mt-1'),
  275. set::href(createLink('project', 'team', "projectID={$project->id}")),
  276. sprintf($lang->project->teamSumCount, $project->teamCount)
  277. )
  278. )
  279. ),
  280. div
  281. (
  282. setClass('project-actions'),
  283. $actionItems ? dropdown
  284. (
  285. set::caret(false),
  286. btn
  287. (
  288. setClass('ghost btn square btn-default'),
  289. set::icon('ellipsis-v')
  290. ),
  291. set::placement('left-end'),
  292. set::menu(array('class' => 'flex p-2 project-menu-actions')),
  293. set::items($actionItems)
  294. ) : null
  295. )
  296. )
  297. )
  298. )
  299. );
  300. }
  301. }
  302. div
  303. (
  304. setID('cards'),
  305. setClass('row cell'),
  306. empty($projectStats) ? div
  307. (
  308. setClass('table-empty-tip w-full'),
  309. span
  310. (
  311. setClass('text-gray'),
  312. $lang->project->empty
  313. ),
  314. hasPriv('project', 'create') ? btn(set(array
  315. (
  316. 'icon' => 'plus',
  317. 'text' => $lang->project->create,
  318. 'class' => 'ml-2',
  319. 'url' => createLink('project', 'createGuide'),
  320. 'data-toggle' => 'modal',
  321. 'data-position' => 'center'
  322. ))) : null
  323. ) : $projectCards,
  324. !empty($projectStats) ? div
  325. (
  326. setID('cardsFooter'),
  327. pager(set(usePager()))
  328. ) : null
  329. );
  330. /* ====== Render page ====== */
  331. render();