Skip to content

Commit 9016e46

Browse files
committed
feat: add alumni overview and alumni badges
1 parent db2487f commit 9016e46

10 files changed

Lines changed: 60 additions & 5 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- AlterTable
2+
ALTER TABLE "User" ADD COLUMN "alumnized_at" DATETIME;

prisma/schema.prisma

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ model User {
3030
pool_year String?
3131
pool_year_num Int?
3232
anonymize_date DateTime?
33+
alumnized_at DateTime?
3334
3435
created_at DateTime
3536
updated_at DateTime

src/handlers/disco.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ export const getDiscoPiscineData = async function(prisma: PrismaClient, year: nu
135135
// For each user, check if they are also a student in the regular cursus
136136
let activeStudents: { [login: string]: boolean } = {};
137137
for (const user of users) {
138+
if (user.alumnized_at) {
139+
activeStudents[user.login] = false; // Alumni are not active students
140+
continue;
141+
}
138142
const cursusUsers = await prisma.cursusUser.findMany({
139143
where: {
140144
user_id: user.id,

src/handlers/piscine.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ export const getCPiscineData = async function(prisma: PrismaClient, year: number
122122
// For each user, check if they are also a student in the regular cursus
123123
let activeStudents: { [login: string]: boolean } = {};
124124
for (const user of users) {
125+
if (user.alumnized_at) {
126+
activeStudents[user.login] = false; // Alumni are not active students
127+
continue;
128+
}
125129
const cursusUsers = await prisma.cursusUser.findMany({
126130
where: {
127131
user_id: user.id,

src/intra/users.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export const syncUser = async function(user: any): Promise<void> {
2323
pool_year: user.pool_year,
2424
pool_year_num: parseInt(user.pool_year),
2525
anonymize_date: new Date(user.anonymize_date),
26+
alumnized_at: user.alumnized_at ? new Date(user.alumnized_at) : null,
2627
updated_at: new Date(user.updated_at),
2728
image: (user.image && user.image.versions && user.image.versions.large) ? user.image.versions.large : null,
2829
},
@@ -40,6 +41,7 @@ export const syncUser = async function(user: any): Promise<void> {
4041
pool_year: user.pool_year,
4142
pool_year_num: parseInt(user.pool_year),
4243
anonymize_date: new Date(user.anonymize_date),
44+
alumnized_at: user.alumnized_at ? new Date(user.alumnized_at) : null,
4345
created_at: new Date(user.created_at),
4446
updated_at: new Date(user.updated_at),
4547
kind: user.kind,

src/routes/users.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ export const setupUsersRoutes = function(app: Express, prisma: PrismaClient): vo
2525
cursus_users: {
2626
some: {
2727
cursus_id: 21,
28-
end_at: null,
28+
end_at: null, // Exclude dropouts
2929
},
3030
},
31+
alumnized_at: null, // Exclude alumni
3132
},
3233
include: {
3334
cursus_users: {
@@ -68,6 +69,7 @@ export const setupUsersRoutes = function(app: Express, prisma: PrismaClient): vo
6869
},
6970
},
7071
},
72+
// Include dropouts and alumni for the year overview
7173
},
7274
include: {
7375
cursus_users: {
@@ -84,6 +86,36 @@ export const setupUsersRoutes = function(app: Express, prisma: PrismaClient): vo
8486
return res.render('users.njk', { subtitle: `Students (${year} cohort)`, cohorts, users, year });
8587
});
8688

89+
app.get('/users/alumni', passport.authenticate('session'), async (req, res) => {
90+
const users = await prisma.user.findMany({
91+
where: {
92+
login: {
93+
not: {
94+
startsWith: '3b3-',
95+
},
96+
},
97+
kind: {
98+
not: "admin",
99+
},
100+
alumnized_at: {
101+
not: null, // Only include alumni
102+
},
103+
},
104+
include: {
105+
cursus_users: {
106+
where: {
107+
cursus_id: 21,
108+
},
109+
},
110+
},
111+
orderBy: [
112+
{ usual_full_name: 'asc' }
113+
],
114+
});
115+
116+
return res.render('users.njk', { subtitle: 'Alumni', users });
117+
});
118+
87119
app.get('/users/staff', passport.authenticate('session'), async (req, res) => {
88120
const users = await prisma.user.findMany({
89121
where: {

static/css/base.css

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
/* *************************************** */
44

55
:root {
6+
--intra: #00BABC;
67
--blue: #3AA2DB;
78
--indigo: #6610f2;
89
--purple: #B73188;
@@ -380,11 +381,19 @@ nav a {
380381
padding: 2px 6px;
381382
font-size: small;
382383
color: var(--white);
383-
background-color: var(--blue);
384+
background-color: var(--gray-dark);
384385
border-radius: 4px;
385386
text-transform: uppercase;
386387
}
387388

389+
.user .badge.student {
390+
background-color: var(--blue);
391+
}
392+
393+
.user .badge.alumni {
394+
background-color: var(--intra); /* same color as this badge on Intra */
395+
}
396+
388397
.user .pool {
389398
font-size: small;
390399
}

templates/disco.njk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
<!-- big li element above, spanning multiple lines -->
7979
<div class="basic-info">
8080
<div class="name">{{ user.usual_full_name | e }}</div>
81-
<div class="login" title="User ID {{ user.id | int }}"><a class="external" target="_blank" href="https://profile.intra.42.fr/users/{{ user.login | e }}/">{{ user.login | e }}</a>{% if activeStudents[user.login] %} <span class="badge" title="User is currently an active student">Student</span>{% endif %}</div>
81+
<div class="login" title="User ID {{ user.id | int }}"><a class="external" target="_blank" href="https://profile.intra.42.fr/users/{{ user.login | e }}/">{{ user.login | e }}</a>{% if activeStudents[user.login] %} <span class="badge student" title="User is currently an active student">Student</span>{% endif %}{% if user.alumnized_at %} <span class="badge alumni" title="User has been alumnized">Alumni</span>{% endif %}</div>
8282
<div class="level">{{ user.cursus_users[0].level | formatFloat }}{{ " (dropout)" if dropouts[user.login] }}</div>
8383
<img class="picture" src="{{ user.image if user.image else "/images/default.png" }}" loading="lazy" />
8484
</div>

templates/piscines.njk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
<!-- big li element above, spanning multiple lines -->
9090
<div class="basic-info">
9191
<div class="name">{{ user.usual_full_name | e }}</div>
92-
<div class="login" title="User ID {{ user.id | int }}"><a class="external" target="_blank" href="https://profile.intra.42.fr/users/{{ user.login | e }}/">{{ user.login | e }}</a>{% if activeStudents[user.login] %} <span class="badge" title="User is currently an active student">Student</span>{% endif %}</div>
92+
<div class="login" title="User ID {{ user.id | int }}"><a class="external" target="_blank" href="https://profile.intra.42.fr/users/{{ user.login | e }}/">{{ user.login | e }}</a>{% if activeStudents[user.login] %} <span class="badge student" title="User is currently an active student">Student</span>{% endif %}{% if user.alumnized_at %} <span class="badge alumni" title="User has been alumnized">Alumni</span>{% endif %}</div>
9393
<div class="level">{{ user.cursus_users[0].level | formatFloat }}{{ " (dropout)" if dropouts[user.login] }}{{ " (potential dropout)" if potentialDropouts[user.login] }}</div>
9494
<img class="picture" src="{{ user.image if user.image else "/images/default.png" }}" loading="lazy" />
9595
</div>

templates/users.njk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<!-- selection of users -->
66
<nav>
77
<a class="userlist-selector" href="/users/students">Students</a>
8+
<a class="userlist-selector" href="/users/alumni">Alumni</a>
89
<a class="userlist-selector" href="/users/pisciners">C Pisciners</a>
910
<a class="userlist-selector" href="/users/disco">Discovery Pisciners</a>
1011
<a class="userlist-selector" href="/users/staff">Staff</a>
@@ -60,7 +61,7 @@
6061
<!-- display user information -->
6162
<li class="user {{ user.cursus_users[0] | markDropout }}">
6263
<div class="name">{{ user.usual_full_name | e }}</div>
63-
<div class="login" title="User ID {{ user.id | int }}"><a class="external" target="_blank" href="https://profile.intra.42.fr/users/{{ user.login | e }}/">{{ user.login | e }}</a></div>
64+
<div class="login" title="User ID {{ user.id | int }}"><a class="external" target="_blank" href="https://profile.intra.42.fr/users/{{ user.login | e }}/">{{ user.login | e }}</a>{% if user.alumnized_at %} <span class="badge alumni" title="User has been alumnized">Alumni</span>{% endif %}</div>
6465
<div class="pool">{{ user.pool_month | e }} {{ user.pool_year | int }}</div>
6566
<img class="picture" src="{{ user.image | e if user.image else "/images/default.png" }}" loading="lazy" />
6667
</li>

0 commit comments

Comments
 (0)