mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 16:46:12 +01:00
feat: add pagination to groups page, api routes
use page instead of after
This commit is contained in:
@@ -103,8 +103,6 @@ get:
|
|||||||
type: boolean
|
type: boolean
|
||||||
sort:
|
sort:
|
||||||
type: string
|
type: string
|
||||||
nextStart:
|
|
||||||
type: number
|
|
||||||
title:
|
title:
|
||||||
type: string
|
type: string
|
||||||
- $ref: ../components/schemas/Breadcrumbs.yaml#/Breadcrumbs
|
- $ref: ../components/schemas/Breadcrumbs.yaml#/Breadcrumbs
|
||||||
|
|||||||
@@ -2,15 +2,15 @@ get:
|
|||||||
tags:
|
tags:
|
||||||
- groups
|
- groups
|
||||||
summary: list groups
|
summary: list groups
|
||||||
description: This operation returns a list of user groups. The number of groups returned is hardcoded to 10.
|
description: This operation returns a list of user groups. The number of groups returned is hardcoded to 15 per page.
|
||||||
parameters:
|
parameters:
|
||||||
- in: query
|
- in: query
|
||||||
name: 'after'
|
name: 'page'
|
||||||
schema:
|
schema:
|
||||||
type: number
|
type: number
|
||||||
required: false
|
required: false
|
||||||
description: An offset used to display a different subset of groups.
|
description: Used for pagination
|
||||||
example: '0'
|
example: '1'
|
||||||
- in: query
|
- in: query
|
||||||
name: 'sort'
|
name: 'sort'
|
||||||
schema:
|
schema:
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
define('admin/manage/groups', [
|
define('admin/manage/groups', [
|
||||||
'categorySelector',
|
|
||||||
'slugify',
|
'slugify',
|
||||||
'api',
|
'api',
|
||||||
'bootbox',
|
'bootbox',
|
||||||
'alerts',
|
'alerts',
|
||||||
], function (categorySelector, slugify, api, bootbox, alerts) {
|
], function (slugify, api, bootbox, alerts) {
|
||||||
const Groups = {};
|
const Groups = {};
|
||||||
|
|
||||||
Groups.init = function () {
|
Groups.init = function () {
|
||||||
@@ -88,30 +87,27 @@ define('admin/manage/groups', [
|
|||||||
return ajaxify.refresh();
|
return ajaxify.refresh();
|
||||||
}
|
}
|
||||||
$('.pagination').addClass('hide');
|
$('.pagination').addClass('hide');
|
||||||
const groupsEl = $('.groups-list');
|
api.get('/api/groups', {
|
||||||
socket.emit('groups.search', {
|
|
||||||
query: queryEl.val(),
|
query: queryEl.val(),
|
||||||
options: {
|
sort: 'date',
|
||||||
sort: 'date',
|
hideEphemeralGroups: true,
|
||||||
},
|
}).then(renderSearchResults)
|
||||||
}, function (err, groups) {
|
.catch(alerts.error);
|
||||||
if (err) {
|
|
||||||
return alerts.error(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
app.parseAndTranslate('admin/manage/groups', 'groups', {
|
|
||||||
groups: groups,
|
|
||||||
categories: ajaxify.data.categories,
|
|
||||||
}, function (html) {
|
|
||||||
groupsEl.find('[data-groupname]').remove();
|
|
||||||
groupsEl.find('tbody').append(html);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
queryEl.on('keyup', utils.debounce(doSearch, 200));
|
queryEl.on('keyup', utils.debounce(doSearch, 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderSearchResults(data) {
|
||||||
|
const groupsEl = $('.groups-list');
|
||||||
|
app.parseAndTranslate('admin/manage/groups', 'groups', {
|
||||||
|
groups: data.groups,
|
||||||
|
categories: ajaxify.data.categories,
|
||||||
|
}, function (html) {
|
||||||
|
groupsEl.find('[data-groupname]').remove();
|
||||||
|
groupsEl.find('tbody').append(html);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return Groups;
|
return Groups;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
define('forum/groups/list', [
|
define('forum/groups/list', [
|
||||||
'forum/infinitescroll', 'benchpress', 'api', 'bootbox', 'alerts',
|
'api', 'bootbox', 'alerts',
|
||||||
], function (infinitescroll, Benchpress, api, bootbox, alerts) {
|
], function (api, bootbox, alerts) {
|
||||||
const Groups = {};
|
const Groups = {};
|
||||||
|
|
||||||
Groups.init = function () {
|
Groups.init = function () {
|
||||||
infinitescroll.init(Groups.loadMoreGroups);
|
|
||||||
|
|
||||||
// Group creation
|
// Group creation
|
||||||
$('button[data-action="new"]').on('click', function () {
|
$('button[data-action="new"]').on('click', function () {
|
||||||
bootbox.prompt('[[groups:new-group.group-name]]', function (name) {
|
bootbox.prompt('[[groups:new-group.group-name]]', function (name) {
|
||||||
@@ -24,67 +22,40 @@ define('forum/groups/list', [
|
|||||||
$('#search-sort').val(params.sort || 'alpha');
|
$('#search-sort').val(params.sort || 'alpha');
|
||||||
|
|
||||||
// Group searching
|
// Group searching
|
||||||
$('#search-text').on('keyup', Groups.search);
|
$('#search-text').on('keyup', utils.debounce(Groups.search, 200));
|
||||||
$('#search-button').on('click', Groups.search);
|
$('#search-button').on('click', Groups.search);
|
||||||
$('#search-sort').on('change', function () {
|
$('#search-sort').on('change', function () {
|
||||||
ajaxify.go('groups?sort=' + $('#search-sort').val());
|
ajaxify.go('groups?sort=' + $('#search-sort').val());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Groups.loadMoreGroups = function (direction) {
|
|
||||||
if (direction < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
infinitescroll.loadMore('/groups', {
|
|
||||||
sort: $('#search-sort').val(),
|
|
||||||
after: $('[component="groups/container"]').attr('data-nextstart'),
|
|
||||||
}, function (data, done) {
|
|
||||||
if (data && data.groups.length) {
|
|
||||||
Benchpress.render('partials/groups/list', {
|
|
||||||
groups: data.groups,
|
|
||||||
}).then(function (html) {
|
|
||||||
$('#groups-list').append(html);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data && data.nextStart) {
|
|
||||||
$('[component="groups/container"]').attr('data-nextstart', data.nextStart);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Groups.search = function () {
|
Groups.search = function () {
|
||||||
const groupsEl = $('#groups-list');
|
api.get('/api/groups', {
|
||||||
const queryEl = $('#search-text');
|
query: $('#search-text').val(),
|
||||||
const sortEl = $('#search-sort');
|
sort: $('#search-sort').val(),
|
||||||
|
filterHidden: true,
|
||||||
|
showMembers: true,
|
||||||
|
hideEphemeralGroups: true,
|
||||||
|
}).then(renderSearchResults)
|
||||||
|
.catch(alerts.error);
|
||||||
|
|
||||||
socket.emit('groups.search', {
|
|
||||||
query: queryEl.val(),
|
|
||||||
options: {
|
|
||||||
sort: sortEl.val(),
|
|
||||||
filterHidden: true,
|
|
||||||
showMembers: true,
|
|
||||||
hideEphemeralGroups: true,
|
|
||||||
},
|
|
||||||
}, function (err, groups) {
|
|
||||||
if (err) {
|
|
||||||
return alerts.error(err);
|
|
||||||
}
|
|
||||||
groups = groups.filter(function (group) {
|
|
||||||
return group.name !== 'registered-users' && group.name !== 'guests';
|
|
||||||
});
|
|
||||||
Benchpress.render('partials/groups/list', {
|
|
||||||
groups: groups,
|
|
||||||
}).then(function (html) {
|
|
||||||
groupsEl.empty().append(html);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function renderSearchResults(data) {
|
||||||
|
app.parseAndTranslate('partials/paginator', {
|
||||||
|
pagination: data.pagination,
|
||||||
|
}).then(function (html) {
|
||||||
|
$('.pagination-container').replaceWith(html);
|
||||||
|
});
|
||||||
|
|
||||||
|
const groupsEl = $('#groups-list');
|
||||||
|
app.parseAndTranslate('partials/groups/list', {
|
||||||
|
groups: data.groups,
|
||||||
|
}).then(function (html) {
|
||||||
|
groupsEl.empty().append(html);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return Groups;
|
return Groups;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
|
|
||||||
define('forum/users', [
|
define('forum/users', [
|
||||||
'benchpress', 'api', 'alerts', 'accounts/invite',
|
'api', 'alerts', 'accounts/invite',
|
||||||
], function (Benchpress, api, alerts, AccountInvite) {
|
], function (api, alerts, AccountInvite) {
|
||||||
const Users = {};
|
const Users = {};
|
||||||
|
|
||||||
let searchResultCount = 0;
|
let searchResultCount = 0;
|
||||||
@@ -88,7 +88,9 @@ define('forum/users', [
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderSearchResults(data) {
|
function renderSearchResults(data) {
|
||||||
Benchpress.render('partials/paginator', { pagination: data.pagination }).then(function (html) {
|
app.parseAndTranslate('partials/paginator', {
|
||||||
|
pagination: data.pagination,
|
||||||
|
}).then(function (html) {
|
||||||
$('.pagination-container').replaceWith(html);
|
$('.pagination-container').replaceWith(html);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ const slugify = require('../slugify');
|
|||||||
const groupsAPI = module.exports;
|
const groupsAPI = module.exports;
|
||||||
|
|
||||||
groupsAPI.list = async (caller, data) => {
|
groupsAPI.list = async (caller, data) => {
|
||||||
const groupsPerPage = 10;
|
const page = parseInt(data.page, 10) || 1;
|
||||||
const start = parseInt(data.after || 0, 10);
|
const groupsPerPage = 15;
|
||||||
|
const start = Math.max(0, page - 1) * groupsPerPage;
|
||||||
const stop = start + groupsPerPage - 1;
|
const stop = start + groupsPerPage - 1;
|
||||||
const groupData = await groups.getGroupsBySort(data.sort, start, stop);
|
const groupData = await groups.getGroupsBySort(data.sort, start, stop);
|
||||||
|
|
||||||
|
|||||||
@@ -14,22 +14,49 @@ const groupsController = module.exports;
|
|||||||
|
|
||||||
groupsController.list = async function (req, res) {
|
groupsController.list = async function (req, res) {
|
||||||
const sort = req.query.sort || 'alpha';
|
const sort = req.query.sort || 'alpha';
|
||||||
|
const page = parseInt(req.query.page, 10) || 1;
|
||||||
const [groupData, allowGroupCreation] = await Promise.all([
|
const [allowGroupCreation, [groupData, pageCount]] = await Promise.all([
|
||||||
groups.getGroupsBySort(sort, 0, 14),
|
|
||||||
privileges.global.can('group:create', req.uid),
|
privileges.global.can('group:create', req.uid),
|
||||||
|
getGroups(req, sort, page),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
res.render('groups/list', {
|
res.render('groups/list', {
|
||||||
groups: groupData,
|
groups: groupData,
|
||||||
allowGroupCreation: allowGroupCreation,
|
allowGroupCreation: allowGroupCreation,
|
||||||
sort: validator.escape(String(sort)),
|
sort: validator.escape(String(sort)),
|
||||||
nextStart: 15,
|
pagination: pagination.create(page, pageCount, req.query),
|
||||||
title: '[[pages:groups]]',
|
title: '[[pages:groups]]',
|
||||||
breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[pages:groups]]' }]),
|
breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[pages:groups]]' }]),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function getGroups(req, sort, page) {
|
||||||
|
const resultsPerPage = req.query.query ? 100 : 15;
|
||||||
|
const start = Math.max(0, page - 1) * resultsPerPage;
|
||||||
|
const stop = start + resultsPerPage - 1;
|
||||||
|
|
||||||
|
if (req.query.query) {
|
||||||
|
const filterHidden = req.query.filterHidden === 'true' || !await user.isAdministrator(req.uid);
|
||||||
|
const groupData = await groups.search(req.query.query, {
|
||||||
|
sort,
|
||||||
|
filterHidden: filterHidden,
|
||||||
|
showMembers: req.query.showMembers === 'true',
|
||||||
|
hideEphemeralGroups: req.query.hideEphemeralGroups === 'true',
|
||||||
|
});
|
||||||
|
const pageCount = Math.ceil(groupData.length / resultsPerPage);
|
||||||
|
|
||||||
|
return [groupData.slice(start, stop + 1), pageCount];
|
||||||
|
}
|
||||||
|
|
||||||
|
const [groupData, groupCount] = await Promise.all([
|
||||||
|
groups.getGroupsBySort(sort, start, stop),
|
||||||
|
groups.getGroupCountBySort(sort),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const pageCount = Math.ceil(groupCount / resultsPerPage);
|
||||||
|
return [groupData, pageCount];
|
||||||
|
}
|
||||||
|
|
||||||
groupsController.details = async function (req, res, next) {
|
groupsController.details = async function (req, res, next) {
|
||||||
const lowercaseSlug = req.params.slug.toLowerCase();
|
const lowercaseSlug = req.params.slug.toLowerCase();
|
||||||
if (req.params.slug !== lowercaseSlug) {
|
if (req.params.slug !== lowercaseSlug) {
|
||||||
|
|||||||
@@ -76,14 +76,22 @@ Groups.getGroupsFromSet = async function (set, start, stop) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Groups.getGroupsBySort = async function (sort, start, stop) {
|
Groups.getGroupsBySort = async function (sort, start, stop) {
|
||||||
|
return await Groups.getGroupsFromSet(sortToSet(sort), start, stop);
|
||||||
|
};
|
||||||
|
|
||||||
|
Groups.getGroupCountBySort = async function (sort) {
|
||||||
|
return await db.sortedSetCard(sortToSet(sort));
|
||||||
|
};
|
||||||
|
|
||||||
|
function sortToSet(sort) {
|
||||||
let set = 'groups:visible:name';
|
let set = 'groups:visible:name';
|
||||||
if (sort === 'count') {
|
if (sort === 'count') {
|
||||||
set = 'groups:visible:memberCount';
|
set = 'groups:visible:memberCount';
|
||||||
} else if (sort === 'date') {
|
} else if (sort === 'date') {
|
||||||
set = 'groups:visible:createtime';
|
set = 'groups:visible:createtime';
|
||||||
}
|
}
|
||||||
return await Groups.getGroupsFromSet(set, start, stop);
|
return set;
|
||||||
};
|
}
|
||||||
|
|
||||||
Groups.getNonPrivilegeGroups = async function (set, start, stop, flags) {
|
Groups.getNonPrivilegeGroups = async function (set, start, stop, flags) {
|
||||||
if (!flags) {
|
if (!flags) {
|
||||||
|
|||||||
Reference in New Issue
Block a user