fix: #12357, properly update lists and counters

This commit is contained in:
Barış Soner Uşaklı
2024-02-22 11:44:22 -05:00
parent 09b4dcd369
commit f34ebcc91b
3 changed files with 120 additions and 92 deletions

View File

@@ -6,24 +6,24 @@ define('forum/groups/details', [
'components',
'coverPhoto',
'pictureCropper',
'translator',
'api',
'slugify',
'categorySelector',
'bootbox',
'alerts',
'helpers',
], function (
memberList,
iconSelect,
components,
coverPhoto,
pictureCropper,
translator,
api,
slugify,
categorySelector,
bootbox,
alerts
alerts,
helpers
) {
const Details = {};
let groupName;
@@ -85,14 +85,19 @@ define('forum/groups/details', [
break;
case 'kick':
translator.translate('[[groups:details.kick-confirm]]', function (translated) {
bootbox.confirm(translated, function (confirm) {
if (!confirm) {
return;
}
bootbox.confirm('[[groups:details.kick-confirm]]', function (confirm) {
if (!confirm) {
return;
}
api.del(`/groups/${ajaxify.data.group.slug}/membership/${uid}`, undefined).then(() => userRow.slideUp().remove()).catch(alerts.error);
});
api.del(`/groups/${ajaxify.data.group.slug}/membership/${uid}`, undefined).then(
() => {
userRow.remove();
$('[component="group/member/count"]').text(
helpers.humanReadableNumber(ajaxify.data.group.memberCount - 1)
);
}
).catch(alerts.error);
});
break;
@@ -105,29 +110,42 @@ define('forum/groups/details', [
break;
case 'join':
api.put('/groups/' + ajaxify.data.group.slug + '/membership/' + (uid || app.user.uid), undefined).then(() => ajaxify.refresh()).catch(alerts.error);
api.put('/groups/' + ajaxify.data.group.slug + '/membership/' + (uid || app.user.uid), undefined).then(
() => ajaxify.refresh()
).catch(alerts.error);
break;
case 'leave':
api.del('/groups/' + ajaxify.data.group.slug + '/membership/' + (uid || app.user.uid), undefined).then(() => ajaxify.refresh()).catch(alerts.error);
api.del('/groups/' + ajaxify.data.group.slug + '/membership/' + (uid || app.user.uid), undefined).then(
() => ajaxify.refresh()
).catch(alerts.error);
break;
case 'accept':
api.put(`/groups/${ajaxify.data.group.slug}/pending/${uid}`).then(() => ajaxify.refresh()).catch(alerts.error);
api.put(`/groups/${ajaxify.data.group.slug}/pending/${uid}`).then(
() => {
userRow.remove();
memberList.refresh();
updatePendingAlertVisibility();
}
).catch(alerts.error);
break;
case 'reject':
api.del(`/groups/${ajaxify.data.group.slug}/pending/${uid}`).then(() => ajaxify.refresh()).catch(alerts.error);
break;
case 'issueInvite':
api.post(`/groups/${ajaxify.data.group.slug}/invites/${uid}`).then(() => ajaxify.refresh()).catch(alerts.error);
api.del(`/groups/${ajaxify.data.group.slug}/pending/${uid}`).then(
() => {
userRow.remove();
memberList.refresh();
updatePendingAlertVisibility();
}
).catch(alerts.error);
break;
case 'acceptInvite':
api.put(`/groups/${ajaxify.data.group.slug}/invites/${app.user.uid}`).then(() => {
if (uid) {
userRow.remove();
memberList.refresh();
} else {
ajaxify.refresh();
}
@@ -139,6 +157,8 @@ define('forum/groups/details', [
api.del(`/groups/${ajaxify.data.group.slug}/invites/${uid || app.user.uid}`).then(() => {
if (uid) {
userRow.remove();
updateInviteAlertVisibility();
memberList.refresh();
} else {
ajaxify.refresh();
}
@@ -268,6 +288,20 @@ define('forum/groups/details', [
});
};
function updatePendingAlertVisibility() {
$('[component="groups/pending/alert"]').toggleClass(
'hidden',
$('[component="groups/pending"] tbody tr').length > 0
);
}
function updateInviteAlertVisibility() {
$('[component="groups/invited/alert"]').toggleClass(
'hidden',
$('[component="groups/invited"] tbody tr').length > 0
);
}
function handleMemberInvitations() {
if (!ajaxify.data.group.isOwner) {
return;
@@ -275,8 +309,9 @@ define('forum/groups/details', [
async function updateList() {
const data = await api.get(`/api/groups/${ajaxify.data.group.slug}`);
const html = await app.parseAndTranslate('groups/details', 'group.invited', { group: data.group });
$('[component="groups/invited"] tbody tr').remove();
$('[component="groups/invited"] tbody').html(html);
updateInviteAlertVisibility();
memberList.refresh();
}
const searchInput = $('[component="groups/members/invite"]');
require(['autocomplete'], function (autocomplete) {
@@ -305,21 +340,19 @@ define('forum/groups/details', [
}
function removeCover() {
translator.translate('[[groups:remove-group-cover-confirm]]', function (translated) {
bootbox.confirm(translated, function (confirm) {
if (!confirm) {
return;
}
bootbox.confirm('[[groups:remove-group-cover-confirm]]', function (confirm) {
if (!confirm) {
return;
}
socket.emit('groups.cover.remove', {
groupName: ajaxify.data.group.name,
}, function (err) {
if (!err) {
ajaxify.refresh();
} else {
alerts.error(err);
}
});
socket.emit('groups.cover.remove', {
groupName: ajaxify.data.group.name,
}, function (err) {
if (!err) {
ajaxify.refresh();
} else {
alerts.error(err);
}
});
});
}

View File

@@ -1,19 +1,36 @@
'use strict';
define('forum/groups/memberlist', ['api', 'bootbox', 'alerts'], function (api, bootbox, alerts) {
define('forum/groups/memberlist', ['api', 'bootbox', 'alerts', 'helpers'], function (api, bootbox, alerts, helpers) {
const MemberList = {};
let groupName;
let templateName;
MemberList.init = function (_templateName) {
templateName = _templateName || 'groups/details';
groupName = ajaxify.data.group.name;
handleMemberAdd();
handleMemberSearch();
handleMemberInfiniteScroll();
};
MemberList.refresh = async function () {
const { group } = await api.get(`/api/groups/${ajaxify.data.group.slug}`);
const html = await parseAndTranslate(group.members);
$('[component="groups/members"] tbody').html(html);
$('[component="group/member/count"]').text(
helpers.humanReadableNumber(group.memberCount)
);
$('[component="group/pending/count"]').text(
helpers.humanReadableNumber(group.pending.length)
);
$('[component="group/invited/count"]').text(
helpers.humanReadableNumber(group.invited.length)
);
ajaxify.data.group.members = group.members;
ajaxify.data.group.memberCount = group.memberCount;
ajaxify.data.group.invited = group.invited;
ajaxify.data.group.pending = group.pending;
};
function handleMemberAdd() {
$('[component="groups/members/add"]').on('click', function () {
app.parseAndTranslate('admin/partials/groups/add-members', {}, function (html) {
@@ -29,7 +46,7 @@ define('forum/groups/memberlist', ['api', 'bootbox', 'alerts'], function (api, b
modal.find('[data-uid][data-selected]').each(function (index, el) {
users.push(foundUsers[$(el).attr('data-uid')]);
});
addUserToGroup(users, function () {
addUsersToGroup(users).then(() => {
modal.modal('hide');
});
},
@@ -65,99 +82,77 @@ define('forum/groups/memberlist', ['api', 'bootbox', 'alerts'], function (api, b
});
}
function addUserToGroup(users, callback) {
function done() {
users = users.filter(function (user) {
return !$('[component="groups/members"] [data-uid="' + user.uid + '"]').length;
});
parseAndTranslate(users, function (html) {
$('[component="groups/members"] tbody').prepend(html);
});
callback();
}
const uids = users.map(function (user) { return user.uid; });
if (groupName === 'administrators') {
socket.emit('admin.user.makeAdmins', uids, function (err) {
if (err) {
return alerts.error(err);
}
done();
});
async function addUsersToGroup(users) {
const uids = users.map(u => u.uid);
if (ajaxify.data.group.name === 'administrators') {
await socket.emit('admin.user.makeAdmins', uids).catch(alerts.error);
} else {
Promise.all(uids.map(uid => api.put('/groups/' + ajaxify.data.group.slug + '/membership/' + uid))).then(done).catch(alerts.error);
await Promise.all(uids.map(uid => api.put('/groups/' + ajaxify.data.group.slug + '/membership/' + uid))).catch(alerts.error);
}
users = users.filter(user => !$('[component="groups/members"] [data-uid="' + user.uid + '"]').length);
const html = await parseAndTranslate(users);
$('[component="groups/members"] tbody').prepend(html);
}
function handleMemberSearch() {
const searchEl = $('[component="groups/members/search"]');
searchEl.on('keyup', utils.debounce(function () {
searchEl.on('keyup', utils.debounce(async function () {
const query = searchEl.val();
api.get(`/groups/${ajaxify.data.group.slug}/members`, { query }, function (err, results) {
if (err) {
return alerts.error(err);
}
parseAndTranslate(results.users, function (html) {
$('[component="groups/members"] tbody').html(html);
$('[component="groups/members"]').attr('data-nextstart', 20);
});
});
const results = await api.get(`/groups/${ajaxify.data.group.slug}/members`, { query });
const html = await parseAndTranslate(results.users);
$('[component="groups/members"] tbody').html(html);
$('[component="groups/members"]').attr('data-nextstart', 20);
}, 250));
}
function handleMemberInfiniteScroll() {
$('[component="groups/members"]').on('scroll', function () {
$('[component="groups/members"]').on('scroll', utils.debounce(function () {
const $this = $(this);
const bottom = ($this[0].scrollHeight - $this.innerHeight()) * 0.9;
if ($this.scrollTop() > bottom && !$('[component="groups/members/search"]').val()) {
loadMoreMembers();
}
});
}, 250));
}
function loadMoreMembers() {
async function loadMoreMembers() {
const members = $('[component="groups/members"]');
if (members.attr('loading')) {
return;
}
members.attr('loading', 1);
api.get(`/groups/${ajaxify.data.group.slug}/members`, {
const data = await api.get(`/groups/${ajaxify.data.group.slug}/members`, {
after: members.attr('data-nextstart'),
}, function (err, data) {
if (err) {
return alerts.error(err);
}
}).catch(alerts.error);
if (data && data.users.length) {
onMembersLoaded(data.users, function () {
members.removeAttr('loading');
members.attr('data-nextstart', data.nextStart);
});
} else {
members.removeAttr('loading');
}
});
if (data && data.users.length) {
await onMembersLoaded(data.users);
members.removeAttr('loading');
members.attr('data-nextstart', data.nextStart);
} else {
members.removeAttr('loading');
}
}
function onMembersLoaded(users, callback) {
async function onMembersLoaded(users) {
users = users.filter(function (user) {
return !$('[component="groups/members"] [data-uid="' + user.uid + '"]').length;
});
parseAndTranslate(users, function (html) {
$('[component="groups/members"] tbody').append(html);
callback();
});
const html = await parseAndTranslate(users);
$('[component="groups/members"] tbody').append(html);
}
function parseAndTranslate(users, callback) {
app.parseAndTranslate(templateName, 'group.members', {
async function parseAndTranslate(users) {
return await app.parseAndTranslate(templateName, 'group.members', {
group: {
members: users,
isOwner: ajaxify.data.group.isOwner,
},
}, callback);
});
}
return MemberList;

View File

@@ -167,7 +167,7 @@ module.exports = function (utils, Benchpress, relative_path) {
if (groupObj.isPending && groupObj.name !== 'administrators') {
return `<button class="btn btn-warning disabled ${btnClass}"><i class="fa fa-clock-o"></i> [[groups:membership.invitation-pending]]</button>`;
} else if (groupObj.isInvited) {
return `<button class="btn btn-link" data-action="rejectInvite" data-group="${groupObj.displayName}">[[groups:membership.reject]]</button><button class="btn btn-success" data-action="acceptInvite" data-group="${groupObj.name}"><i class="fa fa-plus"></i> [[groups:membership.accept-invitation]]</button>`;
return `<button class="btn btn-warning" data-action="rejectInvite" data-group="${groupObj.displayName}">[[groups:membership.reject]]</button><button class="btn btn-success" data-action="acceptInvite" data-group="${groupObj.name}"><i class="fa fa-plus"></i> [[groups:membership.accept-invitation]]</button>`;
} else if (!groupObj.disableJoinRequests && groupObj.name !== 'administrators') {
return `<button class="btn btn-success" data-action="join" data-group="${groupObj.displayName}"><i class="fa fa-plus"></i> [[groups:membership.join-group]]</button>`;
}