Skip to content

Commit 25886c3

Browse files
committed
feat: display assistant members on coalition page
1 parent 0380746 commit 25886c3

File tree

4 files changed

+223
-165
lines changed

4 files changed

+223
-165
lines changed

src/main.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { setupNunjucksFilters } from './handlers/filters';
2525
import { setupExpressMiddleware } from './handlers/middleware';
2626
import { setupLoginRoutes } from './routes/login';
2727
import { setupHomeRoutes } from './routes/home';
28+
import { setupCoalitionRoutes } from './routes/coalitions';
2829
import { setupProfileRoutes } from './routes/profile';
2930
import { setupResultsRoutes } from './routes/results';
3031
import { setupChartRoutes } from './routes/charts';
@@ -110,6 +111,7 @@ const main = async () => {
110111
// Set up remaining routes
111112
setupLoginRoutes(app, prisma);
112113
setupHomeRoutes(app, prisma);
114+
setupCoalitionRoutes(app, prisma);
113115
setupProfileRoutes(app, prisma);
114116
setupResultsRoutes(app, prisma);
115117
setupChartRoutes(app, prisma);

src/routes/coalitions.ts

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import { Express } from 'express';
2+
import passport from 'passport';
3+
import { IntraUser, PrismaClient } from '@prisma/client';
4+
import { ExpressIntraUser } from '../sync/oauth';
5+
import { getCoalitionScore, getBlocAtDate, scoreSumsToRanking, getCoalitionTopContributors, SMALL_CONTRIBUTION_TYPES } from '../utils';
6+
import { ASSISTANT_GROUP_ID, ASSISTANTS_CAN_QUIZ } from '../env';
7+
8+
export const setupCoalitionRoutes = function(app: Express, prisma: PrismaClient): void {
9+
app.get('/coalitions/:coalitionId', passport.authenticate('session', {
10+
keepSessionInfo: true,
11+
}), async (req, res) => {
12+
const coalitionId = parseInt(req.params.coalitionId);
13+
if (!coalitionId || isNaN(coalitionId) || coalitionId <= 0) {
14+
return res.status(400).send('Invalid coalition ID');
15+
}
16+
const user = req.user as ExpressIntraUser;
17+
const now = new Date();
18+
19+
const coalition = await prisma.codamCoalition.findFirst({
20+
where: {
21+
id: parseInt(req.params.coalitionId),
22+
},
23+
include: {
24+
intra_coalition: true,
25+
},
26+
});
27+
if (!coalition) {
28+
return res.status(404).send('Coalition not found');
29+
}
30+
31+
const bloc = await getBlocAtDate(prisma, now);
32+
if (!bloc) {
33+
// No ongoing season, there's no point in viewing this page. Redirect to home.
34+
return res.redirect('/');
35+
}
36+
37+
// Get current coalition score
38+
const coalitionScore = await getCoalitionScore(prisma, coalition.id);
39+
40+
// Get the top 25 contributors of this season
41+
const topContributors = await getCoalitionTopContributors(prisma, coalition.id, 'Top contributors of this season', now, 25);
42+
43+
// Get the top contributors of the past 7 days
44+
const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
45+
if (sevenDaysAgo < bloc.begin_at) {
46+
// If the season started less than 7 days ago, we can't get the top contributors of the past 7 days.
47+
// Get the top contributors since the season's start instead.
48+
sevenDaysAgo.setTime(bloc.begin_at.getTime());
49+
console.log('Season started less than 7 days ago, getting top contributors since season start instead');
50+
}
51+
const topScoresWeek = await prisma.codamCoalitionScore.groupBy({
52+
by: ['user_id'],
53+
_sum: {
54+
amount: true,
55+
},
56+
orderBy: {
57+
_sum: {
58+
amount: 'desc',
59+
},
60+
},
61+
where: {
62+
coalition_id: coalition.id,
63+
created_at: {
64+
gte: sevenDaysAgo,
65+
lte: now,
66+
},
67+
},
68+
take: 10,
69+
});
70+
const topContributorsWeek = await scoreSumsToRanking(prisma, topScoresWeek, 'Top contributors of the past 7 days');
71+
72+
const latestScores = await prisma.codamCoalitionScore.findMany({
73+
where: {
74+
coalition_id: coalition.id,
75+
},
76+
orderBy: {
77+
created_at: 'desc',
78+
},
79+
include: {
80+
user: {
81+
select: {
82+
intra_user: {
83+
select: {
84+
login: true,
85+
usual_full_name: true,
86+
image: true,
87+
},
88+
},
89+
},
90+
},
91+
},
92+
take: 50,
93+
});
94+
95+
const latestBigScores = await prisma.codamCoalitionScore.findMany({
96+
where: {
97+
coalition_id: coalition.id,
98+
OR: [
99+
{
100+
NOT: {
101+
fixed_type_id: {
102+
in: SMALL_CONTRIBUTION_TYPES, // Exclude usually low individual scores
103+
}
104+
},
105+
},
106+
{
107+
fixed_type_id: null, // Do include scores that are not fixed types
108+
}
109+
],
110+
amount: {
111+
gt: 0,
112+
},
113+
created_at: {
114+
gte: sevenDaysAgo,
115+
lte: now,
116+
},
117+
},
118+
orderBy: {
119+
created_at: 'desc',
120+
},
121+
include: {
122+
user: {
123+
select: {
124+
intra_user: {
125+
select: {
126+
login: true,
127+
usual_full_name: true,
128+
image: true,
129+
},
130+
},
131+
},
132+
},
133+
},
134+
take: 25,
135+
});
136+
137+
// Get the staff part of this coalition
138+
const staff = await prisma.intraUser.findMany({
139+
where: {
140+
kind: 'admin',
141+
coalition_users: {
142+
some: {
143+
coalition_id: coalition.id,
144+
},
145+
},
146+
cursus_users: {
147+
some: {
148+
end_at: null, // Make sure to only get active staff members
149+
},
150+
},
151+
},
152+
});
153+
154+
// Get the assistants part of this coalition
155+
let assistants: IntraUser[] = [];
156+
let assistantGroup = null;
157+
if (ASSISTANT_GROUP_ID && ASSISTANTS_CAN_QUIZ) {
158+
assistantGroup = await prisma.intraGroup.findUnique({
159+
where: {
160+
id: ASSISTANT_GROUP_ID,
161+
},
162+
});
163+
assistants = await prisma.intraUser.findMany({
164+
where: {
165+
group_users: {
166+
some: {
167+
group_id: ASSISTANT_GROUP_ID,
168+
},
169+
},
170+
coalition_users: {
171+
some: {
172+
coalition_id: coalition.id,
173+
},
174+
},
175+
},
176+
});
177+
}
178+
179+
return res.render('coalition.njk', {
180+
coalition,
181+
topContributors,
182+
topContributorsWeek,
183+
latestScores,
184+
latestBigScores,
185+
coalitionScore,
186+
staff,
187+
assistantGroup,
188+
assistantsCanQuiz: ASSISTANTS_CAN_QUIZ,
189+
assistants,
190+
});
191+
});
192+
};

src/routes/home.ts

Lines changed: 1 addition & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import passport from 'passport';
33
import { CodamCoalition, PrismaClient } from '@prisma/client';
44
import { isQuizAvailable } from './quiz';
55
import { ExpressIntraUser } from '../sync/oauth';
6-
import { getCoalitionScore, CoalitionScore, getRanking, SingleRanking, getBlocAtDate, scoreSumsToRanking, getCoalitionTopContributors, SMALL_CONTRIBUTION_TYPES, bonusPointsAwardingStarted } from '../utils';
6+
import { getCoalitionScore, CoalitionScore, getRanking, SingleRanking, getBlocAtDate, bonusPointsAwardingStarted } from '../utils';
77

88
export const setupHomeRoutes = function(app: Express, prisma: PrismaClient): void {
99
app.get('/', passport.authenticate('session', {
@@ -162,168 +162,4 @@ export const setupHomeRoutes = function(app: Express, prisma: PrismaClient): voi
162162
rankingBonusPoints,
163163
});
164164
});
165-
166-
app.get('/coalitions/:coalitionId', passport.authenticate('session', {
167-
keepSessionInfo: true,
168-
}), async (req, res) => {
169-
const coalitionId = parseInt(req.params.coalitionId);
170-
if (!coalitionId || isNaN(coalitionId) || coalitionId <= 0) {
171-
return res.status(400).send('Invalid coalition ID');
172-
}
173-
const user = req.user as ExpressIntraUser;
174-
const now = new Date();
175-
176-
const coalition = await prisma.codamCoalition.findFirst({
177-
where: {
178-
id: parseInt(req.params.coalitionId),
179-
},
180-
include: {
181-
intra_coalition: true,
182-
},
183-
});
184-
if (!coalition) {
185-
return res.status(404).send('Coalition not found');
186-
}
187-
188-
const bloc = await getBlocAtDate(prisma, now);
189-
if (!bloc) {
190-
// No ongoing season, there's no point in viewing this page. Redirect to home.
191-
return res.redirect('/');
192-
}
193-
194-
// Get current coalition score
195-
const coalitionScore = await getCoalitionScore(prisma, coalition.id);
196-
197-
// Get the top 25 contributors of this season
198-
const topContributors = await getCoalitionTopContributors(prisma, coalition.id, 'Top contributors of this season', now, 25);
199-
200-
// Get the top contributors of the past 7 days
201-
const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
202-
if (sevenDaysAgo < bloc.begin_at) {
203-
// If the season started less than 7 days ago, we can't get the top contributors of the past 7 days.
204-
// Get the top contributors since the season's start instead.
205-
sevenDaysAgo.setTime(bloc.begin_at.getTime());
206-
console.log('Season started less than 7 days ago, getting top contributors since season start instead');
207-
}
208-
const topScoresWeek = await prisma.codamCoalitionScore.groupBy({
209-
by: ['user_id'],
210-
_sum: {
211-
amount: true,
212-
},
213-
orderBy: {
214-
_sum: {
215-
amount: 'desc',
216-
},
217-
},
218-
where: {
219-
coalition_id: coalition.id,
220-
created_at: {
221-
gte: sevenDaysAgo,
222-
lte: now,
223-
},
224-
},
225-
take: 10,
226-
});
227-
const topContributorsWeek = await scoreSumsToRanking(prisma, topScoresWeek, 'Top contributors of the past 7 days');
228-
229-
const latestScores = await prisma.codamCoalitionScore.findMany({
230-
where: {
231-
coalition_id: coalition.id,
232-
},
233-
orderBy: {
234-
created_at: 'desc',
235-
},
236-
include: {
237-
user: {
238-
select: {
239-
intra_user: {
240-
select: {
241-
login: true,
242-
usual_full_name: true,
243-
image: true,
244-
},
245-
},
246-
},
247-
},
248-
},
249-
take: 50,
250-
});
251-
252-
const latestBigScores = await prisma.codamCoalitionScore.findMany({
253-
where: {
254-
coalition_id: coalition.id,
255-
OR: [
256-
{
257-
NOT: {
258-
fixed_type_id: {
259-
in: SMALL_CONTRIBUTION_TYPES, // Exclude usually low individual scores
260-
}
261-
},
262-
},
263-
{
264-
fixed_type_id: null, // Do include scores that are not fixed types
265-
}
266-
],
267-
amount: {
268-
gt: 0,
269-
},
270-
created_at: {
271-
gte: sevenDaysAgo,
272-
lte: now,
273-
},
274-
},
275-
orderBy: {
276-
created_at: 'desc',
277-
},
278-
include: {
279-
user: {
280-
select: {
281-
intra_user: {
282-
select: {
283-
login: true,
284-
usual_full_name: true,
285-
image: true,
286-
},
287-
},
288-
},
289-
},
290-
},
291-
take: 25,
292-
});
293-
294-
// Get the staff part of this coalition
295-
const staff = await prisma.intraUser.findMany({
296-
where: {
297-
kind: 'admin',
298-
coalition_users: {
299-
some: {
300-
coalition_id: coalition.id,
301-
},
302-
},
303-
cursus_users: {
304-
some: {
305-
end_at: null, // Make sure to only get active staff members
306-
},
307-
},
308-
},
309-
include: {
310-
coalition_users: {
311-
where: {
312-
coalition_id: coalition.id,
313-
},
314-
},
315-
cursus_users: true,
316-
},
317-
});
318-
319-
return res.render('coalition.njk', {
320-
coalition,
321-
topContributors,
322-
topContributorsWeek,
323-
latestScores,
324-
latestBigScores,
325-
coalitionScore,
326-
staff,
327-
});
328-
});
329165
};

0 commit comments

Comments
 (0)