feat: add visibility option to, closes #12942

This commit is contained in:
Barış Soner Uşaklı
2024-11-28 10:12:00 -05:00
parent a16c0c3b89
commit 77382e3b7b
9 changed files with 40 additions and 8 deletions

View File

@@ -20,5 +20,9 @@
"minimum-reputation": "Minimum reputation", "minimum-reputation": "Minimum reputation",
"minimum-reputation-help": "If a user has less than this value they won't be able to use this field", "minimum-reputation-help": "If a user has less than this value they won't be able to use this field",
"delete-field-confirm-x": "Do you really want to delete custom field \"%1\"?", "delete-field-confirm-x": "Do you really want to delete custom field \"%1\"?",
"custom-fields-saved": "Custom fields saved" "custom-fields-saved": "Custom fields saved",
"visibility": "Visibility",
"visibility-all": "Everyone can see the field",
"visibility-loggedin": "Only logged in users can see the field",
"visibility-privileged": "Only privileged users like admins & moderators can see the field"
} }

View File

@@ -51,6 +51,7 @@ define('admin/manage/user/custom-fields', [
icon: el.attr('data-icon'), icon: el.attr('data-icon'),
type: el.attr('data-type'), type: el.attr('data-type'),
'select-options': el.attr('data-select-options'), 'select-options': el.attr('data-select-options'),
visibility: el.attr('data-visibility'),
'min:rep': el.attr('data-min-rep'), 'min:rep': el.attr('data-min-rep'),
}; };
} }

View File

@@ -29,7 +29,7 @@ editController.get = async function (req, res, next) {
const [canUseSignature, canManageUsers, customUserFields] = await Promise.all([ const [canUseSignature, canManageUsers, customUserFields] = await Promise.all([
privileges.global.can('signature', req.uid), privileges.global.can('signature', req.uid),
privileges.admin.can('admin:users', req.uid), privileges.admin.can('admin:users', req.uid),
accountHelpers.getCustomUserFields(userData), accountHelpers.getCustomUserFields(req.uid, userData),
]); ]);
userData.customUserFields = customUserFields; userData.customUserFields = customUserFields;

View File

@@ -129,13 +129,26 @@ helpers.getUserDataByUserSlug = async function (userslug, callerUID, query = {})
return hookData.userData; return hookData.userData;
}; };
helpers.getCustomUserFields = async function (userData) { helpers.getCustomUserFields = async function (callerUID, userData) {
const keys = await db.getSortedSetRange('user-custom-fields', 0, -1); const keys = await db.getSortedSetRange('user-custom-fields', 0, -1);
const allFields = (await db.getObjects(keys.map(k => `user-custom-field:${k}`))).filter(Boolean); const allFields = (await db.getObjects(keys.map(k => `user-custom-field:${k}`))).filter(Boolean);
const isSelf = String(callerUID) === String(userData.uid);
const [isAdmin, isModOfAny] = await Promise.all([
privileges.users.isAdministrator(callerUID),
user.isModeratorOfAnyCategory(callerUID),
]);
const fields = allFields.filter((field) => { const fields = allFields.filter((field) => {
const visibilityCheck = isAdmin || isModOfAny || isSelf || field.visibility === 'all' ||
(
field.visibility === 'loggedin' &&
String(callerUID) !== '0' &&
String(callerUID) !== '-1'
);
const minRep = field['min:rep'] || 0; const minRep = field['min:rep'] || 0;
return userData.reputation >= minRep || meta.config['reputation:disabled']; const repCheck = userData.reputation >= minRep || meta.config['reputation:disabled'];
return visibilityCheck && repCheck;
}); });
fields.forEach((f) => { fields.forEach((f) => {

View File

@@ -25,7 +25,7 @@ profileController.get = async function (req, res, next) {
const [latestPosts, bestPosts, customUserFields] = await Promise.all([ const [latestPosts, bestPosts, customUserFields] = await Promise.all([
getLatestPosts(req.uid, userData), getLatestPosts(req.uid, userData),
getBestPosts(req.uid, userData), getBestPosts(req.uid, userData),
accountHelpers.getCustomUserFields(userData), accountHelpers.getCustomUserFields(req.uid, userData),
posts.parseSignature(userData, req.uid), posts.parseSignature(userData, req.uid),
]); ]);
userData.customUserFields = customUserFields; userData.customUserFields = customUserFields;

View File

@@ -310,6 +310,7 @@ usersController.customFields = async function (req, res) {
field.selectOptionsFormatted = field['select-options'].trim().split('\n').join(', '); field.selectOptionsFormatted = field['select-options'].trim().split('\n').join(', ');
} }
field['min:rep'] = field['min:rep'] || 0; field['min:rep'] = field['min:rep'] || 0;
field.visibility = field.visibility || 'all';
}); });
res.render('admin/manage/users/custom-fields', { fields: fields }); res.render('admin/manage/users/custom-fields', { fields: fields });
}; };

View File

@@ -21,13 +21,14 @@
<th class="text-muted">[[admin/manage/user-custom-fields:key]]</th> <th class="text-muted">[[admin/manage/user-custom-fields:key]]</th>
<th class="text-muted">[[admin/manage/user-custom-fields:name]]</th> <th class="text-muted">[[admin/manage/user-custom-fields:name]]</th>
<th class="text-muted">[[admin/manage/user-custom-fields:type]]</th> <th class="text-muted">[[admin/manage/user-custom-fields:type]]</th>
<th class="text-muted">[[admin/manage/user-custom-fields:visibility]]</th>
<th class="text-muted text-end">[[admin/manage/user-custom-fields:min-rep]]</th> <th class="text-muted text-end">[[admin/manage/user-custom-fields:min-rep]]</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{{ each fields }}} {{{ each fields }}}
<tr data-key="{./key}" data-name="{./name}" data-icon="{./icon}" data-type="{./type}" data-min-rep="{./min:rep}" data-select-options="{./select-options}" class="align-middle"> <tr data-key="{./key}" data-name="{./name}" data-icon="{./icon}" data-type="{./type}" data-min-rep="{./min:rep}" data-select-options="{./select-options}" data-visibility="{./visibility}" class="align-middle">
<td style="width: 32px;"> <td style="width: 32px;">
<a href="#" component="sort/handle" class="btn btn-light btn-sm d-none d-md-block ui-sortable-handle" style="cursor:grab;"><i class="fa fa-arrows-up-down text-muted"></i></a> <a href="#" component="sort/handle" class="btn btn-light btn-sm d-none d-md-block ui-sortable-handle" style="cursor:grab;"><i class="fa fa-arrows-up-down text-muted"></i></a>
</td> </td>
@@ -41,6 +42,9 @@
</div> </div>
{{{ end }}} {{{ end }}}
</td> </td>
<td>
{./visibility}
</td>
<td class="text-end"> <td class="text-end">
{./min:rep} {./min:rep}
</td> </td>

View File

@@ -29,6 +29,15 @@
</div> </div>
</div> </div>
<div class="mb-3">
<label class="form-label">[[admin/manage/user-custom-fields:visibility]]</label>
<select name="visibility" class="form-select">
<option value="all">[[admin/manage/user-custom-fields:visibility-all]]</option>
<option value="loggedin">[[admin/manage/user-custom-fields:visibility-loggedin]]</option>
<option value="privileged">[[admin/manage/user-custom-fields:visibility-privileged]]</option>
</select>
</div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label">[[admin/manage/user-custom-fields:minimum-reputation]]</label> <label class="form-label">[[admin/manage/user-custom-fields:minimum-reputation]]</label>
<input class="form-control" type="number" name="min:rep" value="{./min:rep}" placeholder="0"> <input class="form-control" type="number" name="min:rep" value="{./min:rep}" placeholder="0">

View File

@@ -15,7 +15,7 @@
<label for="downvote:disabled" class="form-check-label">[[admin/settings/reputation:disable-down-voting]]</label> <label for="downvote:disabled" class="form-check-label">[[admin/settings/reputation:disable-down-voting]]</label>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="upvoteVisibility" class="form-check-label">[[admin/settings/reputation:upvote-visibility]]</label> <label for="upvoteVisibility" class="form-label">[[admin/settings/reputation:upvote-visibility]]</label>
<select id="upvoteVisibility" data-field="upvoteVisibility" class="form-select"> <select id="upvoteVisibility" data-field="upvoteVisibility" class="form-select">
<option value="all">[[admin/settings/reputation:upvote-visibility-all]]</option> <option value="all">[[admin/settings/reputation:upvote-visibility-all]]</option>
<option value="loggedin">[[admin/settings/reputation:upvote-visibility-loggedin]]</option> <option value="loggedin">[[admin/settings/reputation:upvote-visibility-loggedin]]</option>
@@ -23,7 +23,7 @@
</select> </select>
</div> </div>
<div> <div>
<label for="downvoteVisibility" class="form-check-label">[[admin/settings/reputation:downvote-visibility]]</label> <label for="downvoteVisibility" class="form-label">[[admin/settings/reputation:downvote-visibility]]</label>
<select id="downvoteVisibility" data-field="downvoteVisibility" class="form-select"> <select id="downvoteVisibility" data-field="downvoteVisibility" class="form-select">
<option value="all">[[admin/settings/reputation:downvote-visibility-all]]</option> <option value="all">[[admin/settings/reputation:downvote-visibility-all]]</option>
<option value="loggedin">[[admin/settings/reputation:downvote-visibility-loggedin]]</option> <option value="loggedin">[[admin/settings/reputation:downvote-visibility-loggedin]]</option>