mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 11:05:54 +01:00 
			
		
		
		
	feat: add privileges shortcut to groups list
fix issues with escape group names
This commit is contained in:
		| @@ -9,7 +9,8 @@ | |||||||
| 	"private": "Private", | 	"private": "Private", | ||||||
| 	"edit": "Edit", | 	"edit": "Edit", | ||||||
| 	"delete": "Delete", | 	"delete": "Delete", | ||||||
| 	"download-csv": "Download CSV", | 	"privileges": "Privileges", | ||||||
|  | 	"download-csv": "CSV", | ||||||
| 	"search-placeholder": "Search", | 	"search-placeholder": "Search", | ||||||
| 	"create": "Create Group", | 	"create": "Create Group", | ||||||
| 	"description-placeholder": "A short description about your group", | 	"description-placeholder": "A short description about your group", | ||||||
|   | |||||||
| @@ -26,6 +26,10 @@ | |||||||
| 			margin: 0; | 			margin: 0; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	[component="category-selector"] { | ||||||
|  | 		max-width: 110px; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| .page-admin-groups { | .page-admin-groups { | ||||||
|   | |||||||
| @@ -900,6 +900,8 @@ paths: | |||||||
|                       cid: |                       cid: | ||||||
|                         type: number |                         type: number | ||||||
|                         description: A category identifier |                         description: A category identifier | ||||||
|  |                       group: | ||||||
|  |                         type: string | ||||||
|                   - $ref: components/schemas/CommonProps.yaml#/CommonProps |                   - $ref: components/schemas/CommonProps.yaml#/CommonProps | ||||||
|   /api/admin/manage/tags: |   /api/admin/manage/tags: | ||||||
|     get: |     get: | ||||||
| @@ -1314,6 +1316,36 @@ paths: | |||||||
|                             - textColor |                             - textColor | ||||||
|                             - createtimeISO |                             - createtimeISO | ||||||
|                             - cover:thumb:url |                             - cover:thumb:url | ||||||
|  |                       categories: | ||||||
|  |                         type: array | ||||||
|  |                         items: | ||||||
|  |                           type: object | ||||||
|  |                           properties: | ||||||
|  |                             cid: | ||||||
|  |                               type: number | ||||||
|  |                               description: A category identifier | ||||||
|  |                             name: | ||||||
|  |                               type: string | ||||||
|  |                             icon: | ||||||
|  |                               type: string | ||||||
|  |                             selected: | ||||||
|  |                               type: boolean | ||||||
|  |                             level: | ||||||
|  |                               type: string | ||||||
|  |                             parentCid: | ||||||
|  |                               type: number | ||||||
|  |                               description: The category identifier for the category that is the immediate | ||||||
|  |                                 ancestor of the current category | ||||||
|  |                             color: | ||||||
|  |                               type: string | ||||||
|  |                             bgColor: | ||||||
|  |                               type: string | ||||||
|  |                             imageClass: | ||||||
|  |                               type: string | ||||||
|  |                           required: | ||||||
|  |                             - cid | ||||||
|  |                             - name | ||||||
|  |                             - icon | ||||||
|                       yourid: |                       yourid: | ||||||
|                         type: number |                         type: number | ||||||
|                   - $ref: components/schemas/Pagination.yaml#/Pagination |                   - $ref: components/schemas/Pagination.yaml#/Pagination | ||||||
|   | |||||||
| @@ -6,7 +6,8 @@ define('admin/manage/group', [ | |||||||
| 	'iconSelect', | 	'iconSelect', | ||||||
| 	'admin/modules/colorpicker', | 	'admin/modules/colorpicker', | ||||||
| 	'translator', | 	'translator', | ||||||
| ], function (memberList, iconSelect, colorpicker, translator) { | 	'categorySelector', | ||||||
|  | ], function (memberList, iconSelect, colorpicker, translator, categorySelector) { | ||||||
| 	var Groups = {}; | 	var Groups = {}; | ||||||
|  |  | ||||||
| 	Groups.init = function () { | 	Groups.init = function () { | ||||||
| @@ -49,7 +50,9 @@ define('admin/manage/group', [ | |||||||
| 			}); | 			}); | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
| 		$('[component="category/list"] [data-cid]').on('click', navigateToCategory); | 		categorySelector.init($('[component="category-selector"]'), function (selectedCategory) { | ||||||
|  | 			navigateToCategory(selectedCategory.cid); | ||||||
|  | 		}); | ||||||
|  |  | ||||||
| 		colorpicker.enable(changeGroupLabelColor, function (hsb, hex) { | 		colorpicker.enable(changeGroupLabelColor, function (hsb, hex) { | ||||||
| 			groupLabelPreview.css('background-color', '#' + hex); | 			groupLabelPreview.css('background-color', '#' + hex); | ||||||
| @@ -142,11 +145,9 @@ define('admin/manage/group', [ | |||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function navigateToCategory() { | 	function navigateToCategory(cid) { | ||||||
| 		var cid = $(this).attr('data-cid'); |  | ||||||
|  |  | ||||||
| 		if (cid) { | 		if (cid) { | ||||||
| 			var url = 'admin/manage/privileges/' + cid + '?group=' + ajaxify.data.group.name; | 			var url = 'admin/manage/privileges/' + cid + '?group=' + ajaxify.data.group.nameEncoded; | ||||||
| 			if (app.flags && app.flags._unsaved === true) { | 			if (app.flags && app.flags._unsaved === true) { | ||||||
| 				translator.translate('[[global:unsaved-changes]]', function (text) { | 				translator.translate('[[global:unsaved-changes]]', function (text) { | ||||||
| 					bootbox.confirm(text, function (navigate) { | 					bootbox.confirm(text, function (navigate) { | ||||||
|   | |||||||
| @@ -1,7 +1,9 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
|  |  | ||||||
| define('admin/manage/groups', ['translator', 'benchpress'], function (translator, Benchpress) { | define('admin/manage/groups', [ | ||||||
|  | 	'translator', 'benchpress', 'categorySelector', | ||||||
|  | ], function (translator, Benchpress, categorySelector) { | ||||||
| 	var	Groups = {}; | 	var	Groups = {}; | ||||||
|  |  | ||||||
| 	var intervalId = 0; | 	var intervalId = 0; | ||||||
| @@ -75,6 +77,13 @@ define('admin/manage/groups', ['translator', 'benchpress'], function (translator | |||||||
| 					break; | 					break; | ||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
|  | 		$('.groups-list [component="category-selector"]').each(function () { | ||||||
|  | 			var nameEncoded = $(this).parents('[data-name-encoded]').attr('data-name-encoded'); | ||||||
|  | 			categorySelector.init($(this), function (selectedCategory) { | ||||||
|  | 				ajaxify.go('admin/manage/privileges/' + selectedCategory.cid + '?group=' + nameEncoded); | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	function handleSearch() { | 	function handleSearch() { | ||||||
|   | |||||||
| @@ -95,9 +95,7 @@ define('admin/manage/privileges', [ | |||||||
| 					$('.privilege-table-container').html(html); | 					$('.privilege-table-container').html(html); | ||||||
| 					Privileges.exposeAssumedPrivileges(); | 					Privileges.exposeAssumedPrivileges(); | ||||||
|  |  | ||||||
| 					if (groupToHighlight) { | 					hightlightRowByGroupName(groupToHighlight); | ||||||
| 						$('[data-group-name="' + groupToHighlight + '"]').addClass('selected'); |  | ||||||
| 					} |  | ||||||
| 				}); | 				}); | ||||||
| 			}); | 			}); | ||||||
| 		}); | 		}); | ||||||
| @@ -224,15 +222,25 @@ define('admin/manage/privileges', [ | |||||||
| 		}); | 		}); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	function highlightRow() { | 	function hightlightRowByGroupName(groupName) { | ||||||
| 		var params = utils.params(); | 		if (groupName) { | ||||||
| 		if (params.group) { | 			var el = $('[data-group-name]').filter(function () { | ||||||
| 			var el = $('[data-group-name="' + params.group + '"]'); | 				return $(this).attr('data-group-name') === groupName; | ||||||
|  | 			}); | ||||||
| 			if (el.length) { | 			if (el.length) { | ||||||
| 				return el.addClass('selected'); | 				el.addClass('selected'); | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 			addGroupToCategory(params.group); | 	function highlightRow() { | ||||||
|  | 		if (ajaxify.data.group) { | ||||||
|  | 			if (hightlightRowByGroupName(ajaxify.data.group)) { | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			addGroupToCategory(ajaxify.data.group); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,13 +21,15 @@ groupsController.list = async function (req, res) { | |||||||
| 	const pageCount = Math.ceil(groupNames.length / groupsPerPage); | 	const pageCount = Math.ceil(groupNames.length / groupsPerPage); | ||||||
| 	const start = (page - 1) * groupsPerPage; | 	const start = (page - 1) * groupsPerPage; | ||||||
| 	const stop = start + groupsPerPage - 1; | 	const stop = start + groupsPerPage - 1; | ||||||
|  |  | ||||||
| 	groupNames = groupNames.slice(start, stop + 1); | 	groupNames = groupNames.slice(start, stop + 1); | ||||||
|  |  | ||||||
|  | 	const allCategories = await categories.buildForSelectAll(); | ||||||
| 	const groupData = await groups.getGroupsData(groupNames); | 	const groupData = await groups.getGroupsData(groupNames); | ||||||
| 	res.render('admin/manage/groups', { | 	res.render('admin/manage/groups', { | ||||||
| 		groups: groupData, | 		groups: groupData, | ||||||
| 		pagination: pagination.create(page, pageCount), | 		pagination: pagination.create(page, pageCount), | ||||||
| 		yourid: req.uid, | 		yourid: req.uid, | ||||||
|  | 		categories: allCategories, | ||||||
| 	}); | 	}); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -41,11 +41,12 @@ privilegesController.get = async function (req, res) { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	}); | 	}); | ||||||
|  | 	const group = req.query.group ? req.query.group : ''; | ||||||
| 	res.render('admin/manage/privileges', { | 	res.render('admin/manage/privileges', { | ||||||
| 		privileges: privilegesData, | 		privileges: privilegesData, | ||||||
| 		categories: categoriesData, | 		categories: categoriesData, | ||||||
| 		selectedCategory: selectedCategory, | 		selectedCategory: selectedCategory, | ||||||
| 		cid: cid, | 		cid: cid, | ||||||
|  | 		group: group, | ||||||
| 	}); | 	}); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -15,15 +15,14 @@ | |||||||
| 					<th>[[admin/manage/groups:badge]]</th> | 					<th>[[admin/manage/groups:badge]]</th> | ||||||
| 					<th>[[admin/manage/groups:properties]]</th> | 					<th>[[admin/manage/groups:properties]]</th> | ||||||
| 					<th class="hidden-xs">[[admin/manage/groups:description]]</th> | 					<th class="hidden-xs">[[admin/manage/groups:description]]</th> | ||||||
| 					<th class="hidden-xs text-right">[[admin/manage/groups:member-count]]</th> |  | ||||||
| 					<th></th> | 					<th></th> | ||||||
| 				</tr> | 				</tr> | ||||||
| 			</thead> | 			</thead> | ||||||
| 			<tbody> | 			<tbody> | ||||||
| 				<!-- BEGIN groups --> | 				<!-- BEGIN groups --> | ||||||
| 				<tr data-groupname="{groups.displayName}"> | 				<tr data-groupname="{groups.displayName}" data-name-encoded="{groups.nameEncoded}"> | ||||||
| 					<td> | 					<td> | ||||||
| 						<a href="{config.relative_path}/admin/manage/groups/{groups.nameEncoded}">{groups.displayName}</a> | 						<a href="{config.relative_path}/admin/manage/groups/{groups.nameEncoded}">{groups.displayName}</a> ({groups.memberCount}) | ||||||
| 					</td> | 					</td> | ||||||
| 					<td> | 					<td> | ||||||
| 						<span class="label label-default" style="color:{groups.textColor}; background-color: {groups.labelColor};"><!-- IF groups.icon --><i class="fa {groups.icon}"></i> <!-- ENDIF groups.icon -->{groups.userTitle}</span> | 						<span class="label label-default" style="color:{groups.textColor}; background-color: {groups.labelColor};"><!-- IF groups.icon --><i class="fa {groups.icon}"></i> <!-- ENDIF groups.icon -->{groups.userTitle}</span> | ||||||
| @@ -42,19 +41,15 @@ | |||||||
| 					<td class="hidden-xs"> | 					<td class="hidden-xs"> | ||||||
| 						<p class="description">{groups.description}</p> | 						<p class="description">{groups.description}</p> | ||||||
| 					</td> | 					</td> | ||||||
| 					<td class="hidden-xs text-right"> |  | ||||||
| 						{groups.memberCount} |  | ||||||
| 					</td> |  | ||||||
| 					<td> | 					<td> | ||||||
| 						<div class="btn-group"> | 						<div class="btn-group"> | ||||||
| 							<button class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown" type="button"><i class="fa fa-fw fa-ellipsis-h"></i></button> | 							<a href="{config.relative_path}/api/admin/groups/{groups.nameEncoded}/csv" class="btn btn-default">[[admin/manage/groups:download-csv]]</a> | ||||||
| 							<ul class="dropdown-menu dropdown-menu-right"> |  | ||||||
| 								<li><a href="{config.relative_path}/admin/manage/groups/{groups.nameEncoded}"><i class="fa fa-fw fa-edit"></i> [[admin/manage/groups:edit]]</a></li> | 							<!-- IMPORT admin/partials/groups/privileges-select-category.tpl --> | ||||||
| 								<li><a href="{config.relative_path}/api/admin/groups/{groups.nameEncoded}/csv"><i class="fa fa-fw fa-file-text"></i> [[admin/manage/groups:download-csv]]</a></li> |  | ||||||
| 							<!-- IF !groups.system --> | 							<!-- IF !groups.system --> | ||||||
| 								<li data-action="delete"><a href="#"><i class="fa fa-fw fa-times"></i> [[admin/manage/groups:delete]]</a></li> | 							<button class="btn btn-danger" data-action="delete"><i class="fa fa-times"></i></button> | ||||||
| 							<!-- ENDIF !groups.system --> | 							<!-- ENDIF !groups.system --> | ||||||
| 							</ul> |  | ||||||
| 						</div> | 						</div> | ||||||
| 					</td> | 					</td> | ||||||
| 				</tr> | 				</tr> | ||||||
|   | |||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | <div component="category-selector" class="btn-group"> | ||||||
|  | 	<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> | ||||||
|  | 		<span>[[admin/manage/groups:privileges]]</span> <span class="caret"></span> | ||||||
|  | 	</button> | ||||||
|  | 	<div component="category-selector-search" class="hidden"> | ||||||
|  | 		<input type="text" class="form-control" autocomplete="off"> | ||||||
|  | 	</div> | ||||||
|  | 	<ul component="category/list" class="dropdown-menu category-dropdown-menu dropdown-menu-right" role="menu"> | ||||||
|  | 		<li component="category/no-matches" role="presentation" class="category hidden"> | ||||||
|  | 			<a role="menu-item">[[search:no-matches]]</a> | ||||||
|  | 		</li> | ||||||
|  | 		{{{each categories}}} | ||||||
|  | 		<li role="presentation" class="category <!-- IF categories.disabledClass -->disabled<!-- ENDIF categories.disabledClass -->" data-cid="{categories.cid}" data-name="{categories.name}" data-parent-cid="{categories.parentCid}"> | ||||||
|  | 			<a role="menu-item">{categories.level}<span component="category-markup"><!-- IF categories.icon --><span class="fa-stack" style="{function.generateCategoryBackground}"><i style="color: {categories.color};" class="fa fa-stack-1x fa-fw {categories.icon}"></i></span><!-- ENDIF categories.icon --> {categories.name}</span></a> | ||||||
|  | 		</li> | ||||||
|  | 		{{{end}}} | ||||||
|  | 	</ul> | ||||||
|  | </div> | ||||||
		Reference in New Issue
	
	Block a user