managepriv.ui.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. $(function()
  2. {
  3. selectedPrivIdList = Object.values(selectedPrivIdList);
  4. recommendSelect = new Array();
  5. $('.priv-footer').on('change', '.check-all', checkAllChange);
  6. $('#privList').on('change', 'tbody > tr > th .check-all', checkAllChange);
  7. $('#privPackageList').on('change', 'tbody > tr .check-all', checkAllChange);
  8. $('#privList').on('change', 'tbody > tr .group-item input[type=checkbox]', groupItemChange);
  9. $('#privPackageList .package-column').on('click', '.privs.popover input[type=checkbox]', groupItemChange);
  10. });
  11. function showPriv()
  12. {
  13. loadPage($.createLink('project', 'managePriv', 'projectID=' + projectID + '&groupID=' + groupID + '&type=' + type));
  14. }
  15. window.handleSideRecommentCheckClick = function($target)
  16. {
  17. const checked = $target.prop('checked');
  18. if($target.attr('data-has-children') == 'true')
  19. {
  20. $target.closest('.checkbox-group').find('ul > li input[type=checkbox]').each(function(){
  21. recommendChange($target, checked);
  22. });
  23. }
  24. else
  25. {
  26. recommendChange($target, checked);
  27. }
  28. updatePrivTree(selectedPrivIdList);
  29. };
  30. window.handlePrivPackageListClick = function(event)
  31. {
  32. const $target = $(event.target);
  33. const $privToggle = $target.closest('.package > .priv-toggle.icon');
  34. if($privToggle.length) return handlePrivToggleClick($privToggle);
  35. const $privsPrivToggle = $target.closest('.privs .priv-toggle.icon');
  36. if($privsPrivToggle.length) return handlePrivsPrivToggle($privsPrivToggle);
  37. const $menuPrivsCheck = $target.closest('.package-column .menus-privs input[type=checkbox]');
  38. if($menuPrivsCheck.length) return handleMenuPrivsCheck($menuPrivsCheck);
  39. const $privsCheckAll = $target.closest('.package-column .privs .check-all');
  40. if($privsCheckAll.length) return handlePropvsCheckAll($privsCheckAll);
  41. }
  42. function handlePrivToggleClick($target)
  43. {
  44. let thisIsOpen = $target.hasClass('open');
  45. $target.closest('#privPackageList').find('.priv-toggle.open').removeClass('open');
  46. $('.privs.popover').remove();
  47. if(thisIsOpen) return;
  48. const $td = $target.closest('td');
  49. const $packages = $td.find('.package');
  50. const $parentPackage = $target.closest('.package');
  51. $target.addClass('open');
  52. var moduleName = $parentPackage.attr('data-module');
  53. var packageID = $parentPackage.attr('data-package');
  54. /* The privs should be inserted after which permission package. */
  55. var perRowPackages = Math.floor($td.width() / $packages.width());
  56. var packageIndex = $parentPackage.index() / 2 ;
  57. var appendIndex = (Math.floor(packageIndex / perRowPackages) + 1) * perRowPackages - 1;
  58. var $privs = $(".privs.hidden[data-module='" + moduleName + "'][data-package='" + packageID + "']")
  59. var $showPrivs = $('<div class="privs popover bottom" data-module="' + moduleName + '" data-package="' + packageID + '">'
  60. + $privs.html().replace(/actions/g, 'showPrivs')
  61. + '</div>');
  62. /* Calculate the triangle position of privs popover. */
  63. var position = $packages.width() * (packageIndex % perRowPackages) + 15;
  64. $showPrivs.find('.arrow').css('left', position + 'px');
  65. if($packages.eq(appendIndex).length == 0)
  66. {
  67. $packages.eq(-1).after($showPrivs);
  68. $showPrivs.css('margin-bottom', '0');
  69. }
  70. else
  71. {
  72. $packages.eq(appendIndex).after($showPrivs);
  73. }
  74. }
  75. function handlePrivsPrivToggle($target)
  76. {
  77. var opened = $target.hasClass('open');
  78. $('#privPackageList .group-item > .priv-toggle.icon').removeClass('open');
  79. $('.menus-privs.popover').remove();
  80. if(!opened)
  81. {
  82. $target.addClass('open');
  83. var moduleName = $target.closest('.privs').attr('data-module');
  84. var packageID = $target.closest('.privs').attr('data-package');
  85. /* The menus privs should be inserted after which priv. */
  86. var perRowPrivs = Math.floor($target.closest('.popover-content').width() / $target.closest('.popover-content').find('.group-item').width());
  87. var privIndex = $target.closest('.group-item').index();
  88. var appendIndex = (Math.floor(privIndex / perRowPrivs) + 1) * perRowPrivs - 1;
  89. var $menusPrivs = $target.closest('.group-item').find('.menus-privs')
  90. var $showPrivs = $('<div class="menus-privs popover bottom" data-module="' + moduleName + '" data-package="' + packageID + '">' + $menusPrivs.html() + '</div>');
  91. /* Calculate the triangle position of privs popover. */
  92. var position = $target.closest('.popover-content').width() * (privIndex % perRowPrivs) + 30;
  93. $showPrivs.find('.arrow').css('left', position + 'px');
  94. if($target.closest('.popover-content').find('.group-item:not(.menus-item)').eq(appendIndex).length == 0)
  95. {
  96. $showPrivs.css('margin-bottom', '0');
  97. $target.closest('.popover-content').find('.group-item:not(.menus-item)').eq(-1).after($showPrivs);
  98. }
  99. else
  100. {
  101. $target.closest('.popover-content').find('.group-item:not(.menus-item)').eq(appendIndex).after($showPrivs);
  102. }
  103. }
  104. }
  105. function handleMenuPrivsCheck($target)
  106. {
  107. var $menusPrivs = $target.closest('.popover-content').find('.menus-item');
  108. var $parentPrivs = $target.closest('.privs').find('.checkbox-primary.check-all');
  109. var allPrivs = $menusPrivs.length;
  110. var selectPrivs = $menusPrivs.find('input[type=checkbox]:checked').length;
  111. if(allPrivs > 0 && allPrivs == selectPrivs)
  112. {
  113. $parentPrivs.find('input').attr('checked', true);
  114. $parentPrivs.find('label').removeClass('checkbox-indeterminate-block');
  115. }
  116. else if(selectPrivs == 0)
  117. {
  118. $parentPrivs.find('input').removeAttr('checked');
  119. $parentPrivs.find('label').removeClass('checkbox-indeterminate-block');
  120. }
  121. else
  122. {
  123. $parentPrivs.find('input').removeAttr('checked');
  124. $parentPrivs.find('label').addClass('checkbox-indeterminate-block');
  125. }
  126. groupItemChange();
  127. }
  128. function handlePropvsCheckAll($target)
  129. {
  130. var checked = $target.find('input[type=checkbox]').prop('checked');
  131. var $children = $target.closest('.package-column').find('.menus-privs .menus-item');
  132. if(checked)
  133. {
  134. $children.find('input').attr('checked', true);
  135. }
  136. else
  137. {
  138. $children.find('input').removeAttr('checked');
  139. }
  140. $children.find('label').removeClass('checkbox-indeterminate-block');
  141. $target.find('label').removeClass('checkbox-indeterminate-block');
  142. changeParentChecked($target, $target.closest('.group-item').attr('data-module'), $target.closest('.group-item').attr('data-package'));
  143. };
  144. /**
  145. * When check all change.
  146. *
  147. * @access public
  148. * @return void
  149. */
  150. function checkAllChange()
  151. {
  152. var id = $(this).find('input[type=checkbox]').attr('id');
  153. var checked = $(this).find('input[type=checkbox]').prop('checked');
  154. if(id == 'allChecker')
  155. {
  156. $('input[type=checkbox]').prop('checked', checked);
  157. if(checked) $('input[type=checkbox]').attr('checked', checked);
  158. if(!checked) $('input[type=checkbox]').removeAttr('checked');
  159. $('tbody .checkbox-indeterminate-block').removeClass('checkbox-indeterminate-block');
  160. }
  161. else if($(this).closest('#privList').length > 0)
  162. {
  163. var moduleName = $(this).closest('th').attr('data-module');
  164. var packageID = $(this).closest('th').hasClass('package') ? $(this).closest('th').attr('data-package') : '';
  165. var $children = $(this).closest('th').hasClass('package') ? $(this).closest('tbody').find('[data-divid=' + moduleName + packageID +']') : $(this).closest('tbody').find('[data-module=' + moduleName +']');
  166. $children.find('input[type=checkbox]').prop('checked', checked);
  167. $children.find('.checkbox-indeterminate-block').removeClass('checkbox-indeterminate-block');
  168. if(checked) $children.find('input[type=checkbox]').attr('checked', checked);
  169. if(!checked) $children.find('input[type=checkbox]').removeAttr('checked');
  170. changeParentChecked($(this), moduleName, packageID);
  171. }
  172. else if($(this).closest('#privPackageList').length > 0)
  173. {
  174. var moduleName = $(this).parent().attr('data-module');
  175. var packageID = $(this).parent().hasClass('package') ? $(this).parent().attr('data-package') : '';
  176. var $children = $(this).parent().hasClass('package') ? $(this).closest('td').find('[data-divid=' + moduleName + packageID + ']') : $(this).closest('tbody').find('[data-module=' + moduleName +']');
  177. $children.find('input[type=checkbox]').prop('checked', checked);
  178. $children.find('.checkbox-indeterminate-block').removeClass('checkbox-indeterminate-block');
  179. if(checked) $children.find('input[type=checkbox]').attr('checked', checked);
  180. if(!checked) $children.find('input[type=checkbox]').removeAttr('checked');
  181. changeParentChecked($(this), moduleName, packageID);
  182. }
  183. updatePrivTree(null);
  184. }
  185. /**
  186. * Change parent item checked.
  187. *
  188. * @access public
  189. * @return void
  190. */
  191. function changeParentChecked($item, moduleName, packageID)
  192. {
  193. var moduleAllPrivs = $item.closest('tbody').find('.group-item[data-module=' + moduleName + ']:not(.menus-browse)').length;
  194. var moduleSelectPrivs = $item.closest('tbody').find('.group-item[data-module=' + moduleName + ']:not(.menus-browse)').find('input[type=checkbox]:checked').length;
  195. var $moduleItem = $item.closest('tbody').find('.module[data-module=' + moduleName + ']');
  196. if($item.closest('tbody').find('.menus.' + moduleName).length > 0)
  197. {
  198. moduleAllPrivs += $item.closest('tbody').find('.menus.' + moduleName + ' input[name^=actions]:not(input[value=browse])').length;
  199. moduleSelectPrivs += $item.closest('tbody').find('.menus.' + moduleName + ' input[name^=actions]:checked:not(input[value=browse])').length;
  200. }
  201. if(moduleSelectPrivs == 0)
  202. {
  203. $moduleItem.find('input[type=checkbox]').prop('checked', false);
  204. $moduleItem.find('label').removeClass('checkbox-indeterminate-block');
  205. }
  206. else if(moduleAllPrivs == moduleSelectPrivs)
  207. {
  208. $moduleItem.find('input[type=checkbox]').prop('checked', true);
  209. $moduleItem.find('label').removeClass('checkbox-indeterminate-block');
  210. }
  211. else
  212. {
  213. $moduleItem.find('input[type=checkbox]').prop('checked', false);
  214. $moduleItem.find('label').addClass('checkbox-indeterminate-block');
  215. }
  216. if(packageID == '')
  217. {
  218. const allModules = $item.closest('tbody').find('.module input[type=checkbox]').length;
  219. const allCheckedModules = $item.closest('tbody').find('.module input[type=checkbox]:checked').length;
  220. $('#allChecker').prop('checked', allModules == allCheckedModules);
  221. return;
  222. }
  223. var packageAllPrivs = $item.closest('tbody').find('.group-item[data-divid=' + moduleName + packageID + ']:not(.menus-browse)').length;
  224. var packageSelectPrivs = $item.closest('tbody').find('.group-item[data-divid=' + moduleName + packageID + ']:not(.menus-browse)').find('input[type=checkbox]:checked').length;
  225. var $packageItem = $item.closest('tbody').find('.package[data-divid=' + moduleName + packageID + ']');
  226. if($item.closest('tbody').find('.menus.' + moduleName).length > 0)
  227. {
  228. packageAllPrivs += $item.closest('tbody').find('.menus.' + moduleName + ' input[name^=actions]:not(input[value=browse])').length;
  229. packageSelectPrivs += $item.closest('tbody').find('.menus.' + moduleName + ' input[name^=actions]:checked:not(input[value=browse])').length;
  230. }
  231. if(packageSelectPrivs == 0)
  232. {
  233. $packageItem.find('input[type=checkbox]').prop('checked', false);
  234. $packageItem.find('label').removeClass('checkbox-indeterminate-block');
  235. }
  236. else if(packageAllPrivs == packageSelectPrivs)
  237. {
  238. $packageItem.find('input[type=checkbox]').prop('checked', true);
  239. $packageItem.find('label').removeClass('checkbox-indeterminate-block');
  240. }
  241. else
  242. {
  243. $packageItem.find('input[type=checkbox]').prop('checked', false);
  244. $packageItem.find('label').addClass('checkbox-indeterminate-block');
  245. }
  246. const allModules = $item.closest('tbody').find('.module input[type=checkbox]').length;
  247. const allCheckedModules = $item.closest('tbody').find('.module input[type=checkbox]:checked').length;
  248. $('#allChecker').prop('checked', allModules == allCheckedModules);
  249. }
  250. /**
  251. * update comp tree after click checkbox-label.
  252. *
  253. * @param obj objTree
  254. * @access public
  255. * @return void
  256. */
  257. function updatePrivTree(privList)
  258. {
  259. if(privList == null)
  260. {
  261. privList = new Array();
  262. $('tbody .group-item input:checked').each(function()
  263. {
  264. var privID = $(this).closest('.group-item').attr('data-id');
  265. if($(this).closest('popover-content').length == 0 && privList.indexOf(privID) < 0) privList.push(privID);
  266. });
  267. selectedPrivIdList = privList;
  268. }
  269. loadTarget($.createLink('group', 'ajaxGetRelatedPrivs'), '.side',
  270. {
  271. method: 'post',
  272. data: {"selectPrivList" : privList.toString(), "recommendSelect": recommendSelect.toString(), "allPrivList": Object.values(allPrivList).toString()},
  273. beforeUpdate: (data) =>
  274. {
  275. const $side = $('.side');
  276. $side.children('.zin-page-css,.zin-page-js,.priv-panel').remove();
  277. $side.append(data);
  278. toggleLoading($side, false);
  279. return false;
  280. }
  281. });
  282. }
  283. /**
  284. * Control the packages select control for a module.
  285. *
  286. * @access public
  287. * @return void
  288. */
  289. window.setSubsetPackages = function()
  290. {
  291. let subset = $(this).val();
  292. $('#packageBox select').addClass('hidden'); // Hide all select first.
  293. $('#packageBox select').val(''); // Unselect all select.
  294. $("select[data-module='" + subset + "']").removeClass('hidden'); // Show the action control for current module.
  295. updatePrivList(subset, '');
  296. }
  297. /**
  298. * Update the action box when subset or package selected.
  299. *
  300. * @param string selectedSubset
  301. * @param string selectedPackages
  302. * @access public
  303. * @return void
  304. */
  305. function updatePrivList(selectedSubset, selectedPackages)
  306. {
  307. $.get($.createLink('group', 'ajaxGetPrivByParents', 'subset=' + selectedSubset + '&packages=' + selectedPackages), function(data)
  308. {
  309. $('#actions').replaceWith(data);
  310. })
  311. }
  312. /**
  313. * Control the actions select control for a package.
  314. *
  315. * @access public
  316. * @return void
  317. */
  318. function setActions()
  319. {
  320. $('#actionBox select').val('');
  321. var selectedSubset = $('[name=module]').val();
  322. var selectedPackages = '|' + $('#packageBox select').not('.hidden').val().join('|') + '|';
  323. updatePrivList(selectedSubset, selectedPackages);
  324. }
  325. window.setNoChecked = function()
  326. {
  327. var noCheckValue = '';
  328. $('tbody .group-item > div > div > input').each(function()
  329. {
  330. if(!$(this).prop('checked') && $(this).attr('data-id') != undefined) noCheckValue = noCheckValue + ',' + $(this).attr('data-id');
  331. });
  332. $('#noChecked').val(noCheckValue);
  333. }
  334. /**
  335. * Whrn group item change.
  336. *
  337. * @param object $item
  338. * @access public
  339. * @return void
  340. */
  341. function groupItemChange()
  342. {
  343. var checked = $(this).prop('checked');
  344. if(checked)
  345. {
  346. $(this).attr('checked', true);
  347. }
  348. else
  349. {
  350. $(this).removeAttr('checked');
  351. }
  352. if($('#privPackageList').length > 0)
  353. {
  354. var dataid = $(this).attr('data-id');
  355. var $priv = $('#privPackageList').find('.group-item input[data-id="' + dataid + '"]');
  356. $priv.prop('checked', checked);
  357. }
  358. var moduleName = $(this).closest('.group-item').attr('data-module');
  359. var packageID = $(this).closest('.group-item').attr('data-package');
  360. changeParentChecked($(this), moduleName, packageID);
  361. var privID = $(this).closest('.group-item').attr('data-id');
  362. if(privID)
  363. {
  364. var index = selectedPrivIdList.indexOf(privID);
  365. if(index < 0 && checked) selectedPrivIdList.push(privID);
  366. if(index > -1 && !checked) selectedPrivIdList.splice(index, 1);
  367. updatePrivTree(selectedPrivIdList);
  368. }
  369. }
  370. /**
  371. * When recommend privs change.
  372. *
  373. * @param object $item
  374. * @param bool $checked
  375. * @access public
  376. * @return void
  377. */
  378. function recommendChange($item, checked)
  379. {
  380. var privModule = $item.attr('data-module');
  381. var privMethod = $item.attr('data-method');
  382. var $actionItem = $('#privList').length > 0 ? $('#privList input[data-id="' + privModule + '-' + privMethod + '"]') : $('#privPackageList input[data-id="' + privModule + '-' + privMethod + '"]');
  383. $actionItem.prop('checked', checked);
  384. if(checked)
  385. {
  386. $item.attr('checked', true);
  387. $actionItem.attr('checked', true);
  388. }
  389. else
  390. {
  391. $item.removeAttr('checked');
  392. $actionItem.removeAttr('checked');
  393. }
  394. var moduleName = $actionItem.closest('tr').find('.package').attr('data-module');
  395. var packageID = $('#privList').length > 0 ? $actionItem.closest('tr').find('.package').attr('data-package') : $actionItem.closest('.privs').attr('data-package');
  396. changeParentChecked($actionItem, moduleName, packageID);
  397. var $parentItem = $item.closest('ul').closest('li').find('input[data-has-children="true"]');
  398. var allItemLength = $item.closest('ul').find('input[type=checkbox]').length;
  399. var checkedItemLength = $item.closest('ul').find('input[type=checkbox]:checked').length;
  400. if(checkedItemLength == 0)
  401. {
  402. $parentItem.removeAttr('checked');
  403. $parentItem.closest('.checkbox-primary').find('label').removeClass('checkbox-indeterminate-block');
  404. }
  405. else if(allItemLength == checkedItemLength)
  406. {
  407. $parentItem.attr('checked', true);
  408. $parentItem.closest('.checkbox-primary').find('label').removeClass('checkbox-indeterminate-block');
  409. }
  410. else
  411. {
  412. $parentItem.removeAttr('checked');
  413. $parentItem.closest('.checkbox-primary').find('label').addClass('checkbox-indeterminate-block');
  414. }
  415. var privID = $item.attr('data-id');
  416. if(privID)
  417. {
  418. var index = selectedPrivIdList.indexOf(privID);
  419. if(index < 0 && checked) selectedPrivIdList.push(privID);
  420. if(index > -1 && !checked) selectedPrivIdList.splice(index, 1);
  421. index = recommendSelect.indexOf(privID);
  422. if(index < 0 && checked) recommendSelect.push(privID);
  423. if(index > -1 && !checked) recommendSelect.splice(index, 1);
  424. }
  425. }