Skip to content

Commit

Permalink
Update topic and group search/filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
ilmartyrk committed Nov 16, 2023
1 parent 40d41d1 commit 1779e40
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 5 deletions.
55 changes: 54 additions & 1 deletion routes/api/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -2177,13 +2177,18 @@ module.exports = function (app) {
const limitMax = 100;
const limitDefault = 26;
const userId = req.user?.userId;
const country = req.query.country;
const language = req.query.language;
const orderBy = req.query.orderBy || 'updatedAt';
const order = (req.query.order && req.query.order.toLowerCase() === 'asc') ? 'ASC' : 'DESC';
let orderBySql = ` ORDER BY`;
switch (orderBy) {
case 'name':
orderBySql += ` g.name `
break;
case 'activity':
orderBySql += `ga.updatedAt`
break;
default:
orderBySql += ` g."updatedAt" `

Expand All @@ -2198,7 +2203,7 @@ module.exports = function (app) {
AND g."deletedAt" IS NULL `;
const name = req.query.name;
if (name) {
where += ` AND g.name ILIKE %:name% `;
where += ` AND g.name ILIKE :search `;
}

const sourcePartnerId = req.query.sourcePartnerId;
Expand All @@ -2211,6 +2216,13 @@ module.exports = function (app) {
memberLevel = ` gmu.level AS "userLevel", `;
memberJoin = ` LEFT JOIN "GroupMemberUsers" gmu ON gmu."groupId" = g.id AND gmu."userId" = :userId `
}
if (country) {
where += ` AND g.country=:country `;
}

if (language) {
where += ` AND g.language=:language `;
}
const groups = await db
.query(`
SELECT
Expand All @@ -2223,17 +2235,55 @@ module.exports = function (app) {
g.country,
g.language,
g.contact,
ga."updatedAt" AS "latestActivity",
g.visibility,
gj.token as "join.token",
gj.level as "join.level",
${memberLevel}
c.id as "creator.id",
c.name as "creator.name",
c.company as "creator.company",
mc.count as "members.users.count",
COALESCE(gtc.count, 0) as "members.topics.count",
gt."topicId" as "members.topics.latest.id",
gt.title as "members.topics.latest.title",
count(*) OVER()::integer AS "countTotal"
FROM "Groups" g
JOIN "Users" c ON c.id = g."creatorId"
LEFT JOIN (
SELECT
MAX("updatedAt") as "updatedAt",
"groupIds"
FROM
"Activities" WHERE array_length("groupIds", 1) > 0
GROUP BY "groupIds" ORDER BY "groupIds"
) ga ON g.id::text = ANY(ga."groupIds")
LEFT JOIN "GroupJoins" gj ON gj."groupId" = g.id
JOIN (
SELECT "groupId", count("userId") AS "count"
FROM "GroupMemberUsers"
WHERE "deletedAt" IS NULL
GROUP BY "groupId"
) AS mc ON (mc."groupId" = g.id)
LEFT JOIN (
SELECT
tmg."groupId",
count(tmg."topicId") AS "count"
FROM "TopicMemberGroups" tmg
WHERE tmg."deletedAt" IS NULL
GROUP BY tmg."groupId"
) AS gtc ON (gtc."groupId" = g.id)
LEFT JOIN (
SELECT
tmg."groupId",
tmg."topicId",
t.title
FROM "TopicMemberGroups" tmg
LEFT JOIN "Topics" t ON (t.id = tmg."topicId")
WHERE tmg."deletedAt" IS NULL
AND t.visibility = 'public'
ORDER BY t."updatedAt" ASC
) AS gt ON (gt."groupId" = g.id)
${memberJoin}
WHERE ${where}
${orderBySql}
Expand All @@ -2247,6 +2297,9 @@ module.exports = function (app) {
sourcePartnerId,
orderBy,
order,
country,
language,
search: `%${name}%`,
offset
},
type: db.QueryTypes.SELECT,
Expand Down
157 changes: 153 additions & 4 deletions routes/api/topic.js
Original file line number Diff line number Diff line change
Expand Up @@ -2071,6 +2071,8 @@ module.exports = function (app) {
const creatorId = req.query.creatorId;
let statuses = req.query.statuses;
const favourite = req.query.favourite;
const country = req.query.country;
const language = req.query.language;
const hasVoted = req.query.hasVoted; // Filter out Topics where User has participated in the voting process.
const showModerated = req.query.showModerated || false;
if (statuses && !Array.isArray(statuses)) {
Expand Down Expand Up @@ -2132,6 +2134,14 @@ module.exports = function (app) {
AND t.title IS NOT NULL
AND COALESCE(tmup.level, tmgp.level, 'none')::"enum_TopicMemberUsers_level" > 'none' `;

let categories = req.query.categories;
if (categories && !Array.isArray(categories)) {
categories = [categories];
}

if (categories && categories.length) {
where += `AND t."categories" @> ARRAY[:categories]::VARCHAR(255)[] `;
}
// All partners should see only Topics created by their site, but our own app sees all.
if (partnerId) {
where += ` AND t."sourcePartnerId" = :partnerId `;
Expand All @@ -2149,6 +2159,14 @@ module.exports = function (app) {
where += ` AND tf."topicId" = t.id AND tf."userId" = :userId`;
}

if (country) {
where += ` AND t.country=:country `;
}

if (language) {
where += ` AND t.language=:language `;
}

if (['true', '1'].includes(hasVoted)) {
where += ` AND EXISTS (SELECT TRUE FROM "VoteLists" vl WHERE vl."voteId" = tv."voteId" AND vl."userId" = :userId LIMIT 1)`;
} else if (['false', '0'].includes(hasVoted)) {
Expand All @@ -2171,6 +2189,12 @@ module.exports = function (app) {
}
}

let title = req.query.title || req.query.search;
if (title) {
title = `%${title}%`;
where += ` AND t.title ILIKE :title `;
}

// TODO: NOT THE MOST EFFICIENT QUERY IN THE WORLD, tune it when time.
// TODO: That casting to "enum_TopicMemberUsers_level". Sequelize does not support naming enums, through inheritance I have 2 enums that are the same but with different name thus different type in PG. Feature request - https://github.com/sequelize/sequelize/issues/2577
const query = `
Expand Down Expand Up @@ -2331,11 +2355,15 @@ module.exports = function (app) {
query,
{
replacements: {
categories: categories,
userId: userId,
partnerId: partnerId,
visibility: visibility,
statuses: statuses,
creatorId: creatorId
creatorId: creatorId,
title: title,
language: language,
country: country
},
type: db.QueryTypes.SELECT,
raw: true,
Expand Down Expand Up @@ -2409,6 +2437,8 @@ module.exports = function (app) {
let returncolumns = '';
let voteResults = false;
let showModerated = req.query.showModerated || false;
let country = req.query.country;
let language = req.query.language;

const offset = parseInt(req.query.offset, 10) ? parseInt(req.query.offset, 10) : 0;
let limit = parseInt(req.query.limit, 10) ? parseInt(req.query.limit, 10) : limitDefault;
Expand Down Expand Up @@ -2491,6 +2521,14 @@ module.exports = function (app) {
where += ' AND t.status IN (:statuses)';
}

if (country) {
where += ` AND t.country=:country `;
}

if (language) {
where += ` AND t.language=:language `;
}

let sourcePartnerId = req.query.sourcePartnerId;
if (sourcePartnerId) {
if (!Array.isArray(sourcePartnerId)) {
Expand Down Expand Up @@ -2637,7 +2675,9 @@ module.exports = function (app) {
statuses: statuses,
limit: limit,
title: title,
offset: offset
offset: offset,
country: country,
language: language
},
type: db.QueryTypes.SELECT,
raw: true,
Expand Down Expand Up @@ -2844,7 +2884,7 @@ module.exports = function (app) {
/**
* Get all member Users of the Topic
*/
app.get('/api/users/:userId/topics/:topicId/members/users', loginCheck(['partner']), isModerator(), hasPermission(TopicMemberUser.LEVELS.read), async function (req, res, next) {
app.get('/api/users/:userId/topics/:topicId/members/users', loginCheck(['partner']), isModerator(), hasPermission(TopicMemberUser.LEVELS.read, true), async function (req, res, next) {
const limitDefault = 10;
const offset = parseInt(req.query.offset, 10) ? parseInt(req.query.offset, 10) : 0;
let limit = parseInt(req.query.limit, 10) ? parseInt(req.query.limit, 10) : limitDefault;
Expand Down Expand Up @@ -2997,7 +3037,116 @@ module.exports = function (app) {
/**
* Get all member Groups of the Topic
*/
app.get('/api/users/:userId/topics/:topicId/members/groups', loginCheck(['partner']), hasPermission(TopicMemberUser.LEVELS.read), async function (req, res, next) {
app.get('/api/topics/:topicId/members/groups', async function (req, res, next) {
const limitDefault = 10;
const offset = parseInt(req.query.offset, 10) ? parseInt(req.query.offset, 10) : 0;
let limit = parseInt(req.query.limit, 10) ? parseInt(req.query.limit, 10) : limitDefault;
const search = req.query.search;
const order = req.query.order;
let sortOrder = req.query.sortOrder || 'ASC';

if (sortOrder && ['asc', 'desc'].indexOf(sortOrder.toLowerCase()) === -1) {
sortOrder = 'ASC';
}

let sortSql = ` ORDER BY `;

if (order) {
switch (order) {
case 'name':
sortSql += ` mg.name ${sortOrder} `;
break;
case 'level':
sortSql += ` mg."level"::"enum_TopicMemberGroups_level" ${sortOrder} `;
break;
case 'members.users.count':
sortSql += ` mg."members.users.count" ${sortOrder} `;
break;
default:
sortSql = ` `
}
} else {
sortSql = ` `;
}

let where = '';
if (search) {
where = `WHERE mg.name ILIKE :search`
}
let userLevelField = '';
let userLevelJoin ='';
if (req.user?.id) {
userLevelField = ` gmu.level as "permission.level", `,
userLevelJoin = ` LEFT JOIN "GroupMemberUsers" gmu ON (gmu."groupId" = g.id AND gmu."userId" = :userId AND gmu."deletedAt" IS NULL) `;
}
try {
const groups = await db
.query(
`
SELECT mg.*,count(*) OVER()::integer AS "countTotal" FROM (
SELECT
g.id,
g.name,
tmg.level,
${userLevelField}
g.visibility,
gmuc.count as "members.users.count"
FROM "TopicMemberGroups" tmg
JOIN "Groups" g ON (tmg."groupId" = g.id)
JOIN (
SELECT
"groupId",
COUNT(*) as count
FROM "GroupMemberUsers"
WHERE "deletedAt" IS NULL
GROUP BY 1
) as gmuc ON (gmuc."groupId" = g.id)
${userLevelJoin}
WHERE tmg."topicId" = :topicId AND g."visibility" = 'public'
AND tmg."deletedAt" IS NULL
AND g."deletedAt" IS NULL
ORDER BY level DESC
) mg
${where}
${sortSql}
LIMIT :limit
OFFSET :offset;`,
{
replacements: {
topicId: req.params.topicId,
userId: req.user?.userId,
search: `%${search}%`,
limit,
offset
},
type: db.QueryTypes.SELECT,
raw: true,
nest: true
}
);

let countTotal = 0;
if (groups && groups.length) {
countTotal = groups[0].countTotal;
}
groups.forEach(function (group) {
delete group.countTotal;
});

return res.ok({
countTotal,
count: groups.length,
rows: groups
});
} catch (err) {
return next(err);
}
});

/**
* Get all member Groups of the Topic
*/
app.get('/api/users/:userId/topics/:topicId/members/groups', loginCheck(['partner']), hasPermission(TopicMemberUser.LEVELS.read, true), async function (req, res, next) {
const limitDefault = 10;
const offset = parseInt(req.query.offset, 10) ? parseInt(req.query.offset, 10) : 0;
let limit = parseInt(req.query.limit, 10) ? parseInt(req.query.limit, 10) : limitDefault;
Expand Down

0 comments on commit 1779e40

Please sign in to comment.