diff --git a/src/app/_components/NavBar/navDef.ts b/src/app/_components/NavBar/navDef.ts index ed677c7fa..216e693d9 100644 --- a/src/app/_components/NavBar/navDef.ts +++ b/src/app/_components/NavBar/navDef.ts @@ -8,7 +8,6 @@ import { faShoppingCart, faComment, faCamera, - faList, faCircleInfo, faNewspaper, faCalendar, @@ -127,12 +126,6 @@ export const itemsForMenu: NavItem[] = [ show: 'all', icon: faCamera, }, - { - name: 'Klasselister', - href: '/userlist', - show: 'loggedIn', - icon: faList, - }, { name: 'Om Omega', href: '/articles/om%20omega', diff --git a/src/app/users/[username]/page.tsx b/src/app/users/[username]/page.tsx index bb0062608..98e49439d 100644 --- a/src/app/users/[username]/page.tsx +++ b/src/app/users/[username]/page.tsx @@ -20,7 +20,7 @@ export type PropTypes = { export default async function User({ params }: PropTypes) { const session = await Session.fromNextAuth() if ((await params).username === 'me') { - if (!session.user) return notFound() + if (!session.user) redirect('/login') redirect(`/users/${session.user.username}`) //This throws. } const profileRes = await readUserProfileAction({ params: { username: (await params).username } }) @@ -33,6 +33,9 @@ export default async function User({ params }: PropTypes) { const studyProgrammes = profile.user.memberships.filter(membership => membership.group.groupType === 'STUDY_PROGRAMME') .map(membership => membership.group.studyProgramme).filter(membership => membership !== null) + const classes = profile.user.memberships.filter(membership => membership.group.groupType === 'CLASS') + .map(membership => membership.group.class).filter(membership => membership !== null) + const omegaMembership = profile.user.memberships .find(membership => membership.group.groupType === 'OMEGA_MEMBERSHIP_GROUP') if (!omegaMembership) { @@ -66,6 +69,9 @@ export default async function User({ params }: PropTypes) { {studyProgramme.name} {`(${studyProgramme.code})`}

)} + { classes.map((classGroup, i) => +

{classGroup.year}. årstrinn

+ )}
{ committeeMemberships.filter(membership => membership.active).map(membership => diff --git a/src/prisma/seeder/src/development/seedDevEvents.ts b/src/prisma/seeder/src/development/seedDevEvents.ts index 17b1114bd..e023a520b 100644 --- a/src/prisma/seeder/src/development/seedDevEvents.ts +++ b/src/prisma/seeder/src/development/seedDevEvents.ts @@ -54,6 +54,24 @@ export default async function seedDevEvents(prisma: PrismaClient) { } }) + const ohmaBirthday = await eventOperations.create({ + prisma, + bypassAuth: true, + data: { + name: 'Ohma sin bursdag', + location: 'Ohma', + eventStart: startDate, + eventEnd: endDate, + canBeViewdBy: 'ALL', + takesRegistration: true, + waitingList: true, + places: 50, + registrationStart: today, + registrationEnd: tomorrow, + tagIds: [], + } + }) + const someUsers = await prisma.user.findMany({ take: 10, select: { @@ -67,4 +85,18 @@ export default async function seedDevEvents(prisma: PrismaClient) { userId: user.id })) }) + + const aLotOfUsers = await prisma.user.findMany({ + take: 70, + select: { + id: true + } + }) + + await prisma.eventRegistration.createMany({ + data: aLotOfUsers.map(user => ({ + eventId: ohmaBirthday.id, + userId: user.id + })) + }) } diff --git a/src/prisma/seeder/src/development/seedDevUsers.ts b/src/prisma/seeder/src/development/seedDevUsers.ts index 090f82199..6dccff3ca 100644 --- a/src/prisma/seeder/src/development/seedDevUsers.ts +++ b/src/prisma/seeder/src/development/seedDevUsers.ts @@ -1,35 +1,55 @@ import { hashAndEncryptPassword } from '@/auth/passwordHash' +import { type SeederImage, seedImage } from '@/seeder/src/seedImages' import { v4 as uuid } from 'uuid' -import type { Prisma } from '@prisma/client' -import { OmegaMembershipLevel, type PrismaClient } from '@prisma/client' +import { OmegaMembershipLevel, type PrismaClient, type Prisma } from '@prisma/client' import { randomInt } from 'crypto' +import { readdir } from 'fs/promises' +import { join, dirname } from 'path' +import { fileURLToPath } from 'url' + +const fileName = fileURLToPath(import.meta.url) +const directoryName = dirname(fileName) +const profileImageFSLocation = join(directoryName, '..', '..', 'standard_store', 'images', 'dev_profile_images') + +async function seedDevProfileImages(prisma: PrismaClient) { + let files = await readdir(profileImageFSLocation) + + files = files.filter(file => { + const filenameS = file.split('.') + const ext = filenameS[filenameS.length - 1] + return ext === 'jpg' + }) + + return await Promise.all(files.map(async file => { + const fileS = file.split('.') + + const name = fileS[0] + + const imageConfig: SeederImage = { + special: null, + name, + alt: `Bilde av ${name}`, + credit: null, + license: null, + collection: 'PROFILEIMAGES', + fsLocation: file, + } + + return await seedImage(prisma, profileImageFSLocation, files, imageConfig) + })) +} export default async function seedDevUsers(prisma: PrismaClient) { - const fn = [ - 'anne', 'johan', 'pål', 'lars', 'lasse', 'leo', 'noa', - 'trude', 'andreas', 'nora', 'knut', 'anne', 'sara', 'frikk', 'merete', 'klara', - 'britt helen', 'fiola', 'mika', 'helle', 'jesper' + const firstNames = [ + 'Anne', 'Johan', 'Pål', 'Lars', 'Lasse', 'Leo', 'Noa', + 'Trude', 'Andreas', 'Nora', 'Knut', 'Anne', 'Sara', + 'Frikk', 'Merete', 'Klara', 'Britt Helen', 'Fiola', + 'Mika', 'Helle', 'Jesper', ] - const ln = [ - 'hansen', 'johansen', 'olsen', 'larsen', 'larsen', 'leosdatter', - 'noasdatter', 'trudesdatter', 'lien', 'svendsen', - 'mattisen', 'mørk', 'ruud', 'hansen', 'johansen', 'olsen', - 'larsen', 'larsen', 'leosdatter', 'noasdatter', 'trudesdatter', - 'lien', 'svendsen', 'mattisen', 'mørk', 'ruud', 'hansen', 'johansen', 'olsen', 'larsen', - 'larsen', 'leosdatter', 'noasdatter', 'trudesdatter', 'lien', - 'svendsen', 'mattisen', 'mørk', 'ruud', 'hansen', 'johansen', 'olsen', 'larsen', 'larsen', - // 'leosdatter', 'noasdatter', 'trudesdatter', 'lien', 'svendsen', 'mattisen', - // 'mørk', 'ruud', 'hansen', 'johansen', 'olsen', 'larsen', 'larsen', 'leosdatter', - // 'noasdatter', 'trudesdatter', 'lien', 'svendsen', 'mattisen', 'mørk', - // 'ruud', 'hansen', 'johansen', 'olsen', 'larsen', 'larsen', 'leosdatter', - // 'noasdatter', 'trudesdatter', 'lien', 'svendsen', 'mattisen', 'mørk', 'ruud', 'hansen', 'johansen', - // 'olsen', 'larsen', 'larsen', 'leosdatter', 'noasdatter', 'trudesdatter', - // 'lien', 'svendsen', 'mattisen', 'mørk', 'ruud', 'hansen', 'johansen', 'olsen', 'larsen', 'larsen', 'leosdatter', - // 'noasdatter', 'trudesdatter', 'lien', 'svendsen', 'mattisen', 'mørk', 'ruud', - // 'hansen', 'johansen', 'olsen', 'larsen', 'larsen', 'leosdatter', - // 'noasdatter', 'trudesdatter', 'lien', 'svendsen', 'mattisen', 'mørk', 'ruud' - ] + const profileImages = await seedDevProfileImages(prisma) + + const lastNames = profileImages.map(image => (image ? image.name.replaceAll('-', ' ') : 'Navnløs')) const passwordHash = await hashAndEncryptPassword('password') @@ -47,12 +67,24 @@ export default async function seedDevUsers(prisma: PrismaClient) { const allStudyProgrammes = await prisma.studyProgramme.findMany() const allCommittees = await prisma.committee.findMany() + const allClasses = await prisma.class.findMany() + + Promise.all(firstNames.map(async (firstName, i) => { + await Promise.all(lastNames.map(async (lastName, j) => { + // Randomly remove profile images for 5% of users. + const image = (Math.random() < 0.95) ? profileImages.find(img => (img?.name === lastName)) : undefined + + const username = `${firstName}${lastName}${i + 1}${j}` + .toLowerCase() + .replace(/å/g, 'aa') // special cases for norwegian letters + .replace(/æ/g, 'ae') + .replace(/ø/g, 'oe') + .normalize('NFD') // decompose into letter + diacritics, i.e. 'é' -> 'e´' + .replace(/[^a-zA-Z0-9]/g, '') // only keep ASCII alphanumeric characters - Promise.all(fn.map(async (firstName, i) => { - await Promise.all(ln.map(async (lastName, j) => { const user = await prisma.user.upsert({ where: { - username: `${firstName}${i}${j}` + username, }, update: { @@ -61,14 +93,21 @@ export default async function seedDevUsers(prisma: PrismaClient) { firstname: firstName, lastname: lastName, email: uuid(), - username: `${firstName}${i}${j}`, - studentCard: `${firstName}-${i}-${j}`, + username, + studentCard: `${username}s studentkort`, credentials: { create: { passwordHash, }, }, acceptedTerms: new Date(), + ...(image ? { + image: { + connect: { + id: image.id, + }, + }, + } : {}), }, }) @@ -92,7 +131,16 @@ export default async function seedDevUsers(prisma: PrismaClient) { order: latestOrder.order }) - if (Math.random() > 0.9) { + const classMember = allClasses[randomInt(allClasses.length)] + memberships.push({ + groupId: classMember.groupId, + userId: user.id, + admin: false, + active: true, + order: latestOrder.order, + }) + + if (Math.random() > 0.8) { const committee = allCommittees[randomInt(allCommittees.length)] memberships.push({ @@ -203,7 +251,7 @@ export default async function seedDevUsers(prisma: PrismaClient) { studentCard: 'vever', credentials: { create: { - passwordHash: 'password', + passwordHash, }, }, emailVerified: new Date(), diff --git a/src/prisma/seeder/src/dobbelOmega/dobbelOmega.ts b/src/prisma/seeder/src/dobbelOmega/dobbelOmega.ts index 42d537059..4a1d90669 100644 --- a/src/prisma/seeder/src/dobbelOmega/dobbelOmega.ts +++ b/src/prisma/seeder/src/dobbelOmega/dobbelOmega.ts @@ -10,8 +10,8 @@ import { UserMigrator } from './migrateUsers' import migrateCommittees from './migrateCommittees' import seedProdPermissions from './seedProdPermissions' import manifest from '@/seeder/src/logger' -import type { PrismaClient as PrismaClientPn } from '@prisma/client' import { PrismaClient as PrismaClientVeven } from '@/prisma-dobbel-omega/client' +import type { PrismaClient as PrismaClientPn } from '@prisma/client' /** * !DobbelOmega! diff --git a/src/prisma/seeder/src/seedImages.ts b/src/prisma/seeder/src/seedImages.ts index d8ea7cea5..8d9d22564 100644 --- a/src/prisma/seeder/src/seedImages.ts +++ b/src/prisma/seeder/src/seedImages.ts @@ -1,10 +1,13 @@ -import { seedImageConfig, seedSpecialImageConfig, seedLicenseConfig } from './seedImagesConfig' +import { + seedImageConfig, seedSpecialImageConfig, seedLicenseConfig +} from './seedImagesConfig' import { v4 as uuid } from 'uuid' import sharp from 'sharp' import { readdir, copyFile, mkdir } from 'fs/promises' import path, { join, dirname } from 'path' import { fileURLToPath } from 'url' -import type { PrismaClient } from '@prisma/client' +import type { ImageSeedConfigBase } from './seedImagesConfig' +import type { Image, PrismaClient } from '@prisma/client' const fileName = fileURLToPath(import.meta.url) const directoryName = dirname(fileName) @@ -18,6 +21,88 @@ export const imageSizes = { const standardLocation = join(directoryName, '..', 'standard_store', 'images') export const imageStoreLocation = join(directoryName, '..', '..', '..', '..', 'store', 'images') +export type SeederImage = ImageSeedConfigBase & Pick + +export async function seedImage( + prisma: PrismaClient, + fileLocation: string, + files: string[], + image: SeederImage +): Promise { + const file = files.find(file_ => file_ === image.fsLocation) + if (!file) throw new Error(`File ${image.fsLocation} not found in standard_store/images`) + + const ext = file.split('.')[1] + if (!['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(ext)) { + console.log(`skipping image ${file}`) + return null + } + + const bigPath = path.join(fileLocation, file) + + //full size version of the image + const fsLocationOriginal = `${uuid()}.${ext}` + await copyFile( + bigPath, + join(imageStoreLocation, fsLocationOriginal) + ) + + //create small size version of the image + const fsLocationSmallSize = `${uuid()}.${ext}` + const smallPath = path.join(imageStoreLocation, fsLocationSmallSize) + await sharp(bigPath).resize(imageSizes.small, imageSizes.small, { + fit: sharp.fit.inside, + withoutEnlargement: true + }).toFile(smallPath) + + //create medium size version of the image + const fsLocationMediumSize = `${uuid()}.${ext}` + const mediumPath = path.join(imageStoreLocation, fsLocationMediumSize) + await sharp(bigPath).resize(imageSizes.medium, imageSizes.medium, { + fit: sharp.fit.inside, + withoutEnlargement: true + }).toFile(mediumPath) + + // Create Large size version of the image + const fsLocationLargeSize = `${uuid()}.${ext}` + const largePath = path.join(imageStoreLocation, fsLocationLargeSize) + await sharp(bigPath).resize(imageSizes.large, imageSizes.large, { + fit: sharp.fit.inside, + withoutEnlargement: true + }).toFile(largePath) + + //Delete all images with image.name + await prisma.image.deleteMany({ + where: { + name: image.name + } + }) + + return await prisma.image.create({ + data: { + name: image.name, + alt: image.alt, + credit: image.credit, + license: image.license ? { + connect: { + name: image.license + } + } : undefined, + fsLocationOriginal, + fsLocationSmallSize, + fsLocationMediumSize, + fsLocationLargeSize, + extOriginal: ext, + special: image.special, + collection: { + connect: { + name: image.collection + } + } + } + }) +} + /** * This functions seeds all images in standard_store/images, * both the ones that are special and the ones that are not. @@ -47,78 +132,7 @@ export default async function seedImages(prisma: PrismaClient) { //Seed all images await Promise.all(allImages.map(async (image) => { - const file = files.find(file_ => file_ === image.fsLocation) - if (!file) throw new Error(`File ${image.fsLocation} not found in standard_store/images`) - - const ext = file.split('.')[1] - if (!['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(ext)) { - console.log(`skipping image ${file}`) - return - } - - //full size version of the image - const fsLocationOriginal = `${uuid()}.${ext}` - await copyFile( - join(standardLocation, file), - join(imageStoreLocation, fsLocationOriginal) - ) - - const bigPath = path.join(standardLocation, file) - - //create small size version of the image - const fsLocationSmallSize = `${uuid()}.${ext}` - const smallPath = path.join(imageStoreLocation, fsLocationSmallSize) - await sharp(bigPath).resize(imageSizes.small, imageSizes.small, { - fit: sharp.fit.inside, - withoutEnlargement: true - }).toFile(smallPath) - - //create medium size version of the image - const fsLocationMediumSize = `${uuid()}.${ext}` - const mediumPath = path.join(imageStoreLocation, fsLocationMediumSize) - await sharp(bigPath).resize(imageSizes.medium, imageSizes.medium, { - fit: sharp.fit.inside, - withoutEnlargement: true - }).toFile(mediumPath) - - // Create Large size version of the image - const fsLocationLargeSize = `${uuid()}.${ext}` - const largePath = path.join(imageStoreLocation, fsLocationLargeSize) - await sharp(bigPath).resize(imageSizes.large, imageSizes.large, { - fit: sharp.fit.inside, - withoutEnlargement: true - }).toFile(largePath) - - //Delete all images with image.name - await prisma.image.deleteMany({ - where: { - name: image.name - } - }) - - await prisma.image.create({ - data: { - name: image.name, - alt: image.alt, - credit: image.credit, - license: image.license ? { - connect: { - name: image.license - } - } : undefined, - fsLocationOriginal, - fsLocationSmallSize, - fsLocationMediumSize, - fsLocationLargeSize, - extOriginal: ext, - special: image.special, - collection: { - connect: { - name: image.collection - } - } - } - }) + await seedImage(prisma, standardLocation, files, image) })) } diff --git a/src/prisma/seeder/src/seedImagesConfig.ts b/src/prisma/seeder/src/seedImagesConfig.ts index 63a4fa1db..2a7c2e29e 100644 --- a/src/prisma/seeder/src/seedImagesConfig.ts +++ b/src/prisma/seeder/src/seedImagesConfig.ts @@ -18,7 +18,7 @@ export const seedLicenseConfig = [ type licenseName = typeof seedLicenseConfig[number]['name'] -type ImageSeedConfigBase = { +export type ImageSeedConfigBase = { name: string, alt: string, fsLocation: string, //location in standard_store/images diff --git "a/src/prisma/seeder/standard_store/images/dev_profile_images/Bj\303\270rn.jpg" "b/src/prisma/seeder/standard_store/images/dev_profile_images/Bj\303\270rn.jpg" new file mode 100644 index 000000000..d697d4b42 Binary files /dev/null and "b/src/prisma/seeder/standard_store/images/dev_profile_images/Bj\303\270rn.jpg" differ diff --git a/src/prisma/seeder/standard_store/images/dev_profile_images/Due.jpg b/src/prisma/seeder/standard_store/images/dev_profile_images/Due.jpg new file mode 100644 index 000000000..59f2e4355 Binary files /dev/null and b/src/prisma/seeder/standard_store/images/dev_profile_images/Due.jpg differ diff --git a/src/prisma/seeder/standard_store/images/dev_profile_images/Ekorn.jpg b/src/prisma/seeder/standard_store/images/dev_profile_images/Ekorn.jpg new file mode 100644 index 000000000..c92749ee8 Binary files /dev/null and b/src/prisma/seeder/standard_store/images/dev_profile_images/Ekorn.jpg differ diff --git a/src/prisma/seeder/standard_store/images/dev_profile_images/Elefant.jpg b/src/prisma/seeder/standard_store/images/dev_profile_images/Elefant.jpg new file mode 100644 index 000000000..ab62f5936 Binary files /dev/null and b/src/prisma/seeder/standard_store/images/dev_profile_images/Elefant.jpg differ diff --git a/src/prisma/seeder/standard_store/images/dev_profile_images/Frosk.jpg b/src/prisma/seeder/standard_store/images/dev_profile_images/Frosk.jpg new file mode 100644 index 000000000..835797f6e Binary files /dev/null and b/src/prisma/seeder/standard_store/images/dev_profile_images/Frosk.jpg differ diff --git "a/src/prisma/seeder/standard_store/images/dev_profile_images/G\303\245s.jpg" "b/src/prisma/seeder/standard_store/images/dev_profile_images/G\303\245s.jpg" new file mode 100644 index 000000000..57b8b7115 Binary files /dev/null and "b/src/prisma/seeder/standard_store/images/dev_profile_images/G\303\245s.jpg" differ diff --git a/src/prisma/seeder/standard_store/images/dev_profile_images/Hest.jpg b/src/prisma/seeder/standard_store/images/dev_profile_images/Hest.jpg new file mode 100644 index 000000000..b6fba8fcf Binary files /dev/null and b/src/prisma/seeder/standard_store/images/dev_profile_images/Hest.jpg differ diff --git a/src/prisma/seeder/standard_store/images/dev_profile_images/Kanin.jpg b/src/prisma/seeder/standard_store/images/dev_profile_images/Kanin.jpg new file mode 100644 index 000000000..0b46f1b02 Binary files /dev/null and b/src/prisma/seeder/standard_store/images/dev_profile_images/Kanin.jpg differ diff --git "a/src/prisma/seeder/standard_store/images/dev_profile_images/L\303\270ve.jpg" "b/src/prisma/seeder/standard_store/images/dev_profile_images/L\303\270ve.jpg" new file mode 100644 index 000000000..d0d690214 Binary files /dev/null and "b/src/prisma/seeder/standard_store/images/dev_profile_images/L\303\270ve.jpg" differ diff --git "a/src/prisma/seeder/standard_store/images/dev_profile_images/Papeg\303\270ye.jpg" "b/src/prisma/seeder/standard_store/images/dev_profile_images/Papeg\303\270ye.jpg" new file mode 100644 index 000000000..cbd642d8b Binary files /dev/null and "b/src/prisma/seeder/standard_store/images/dev_profile_images/Papeg\303\270ye.jpg" differ diff --git "a/src/prisma/seeder/standard_store/images/dev_profile_images/P\303\245fugl.jpg" "b/src/prisma/seeder/standard_store/images/dev_profile_images/P\303\245fugl.jpg" new file mode 100644 index 000000000..87bbef9ba Binary files /dev/null and "b/src/prisma/seeder/standard_store/images/dev_profile_images/P\303\245fugl.jpg" differ diff --git a/src/prisma/seeder/standard_store/images/dev_profile_images/README.md b/src/prisma/seeder/standard_store/images/dev_profile_images/README.md new file mode 100644 index 000000000..9e77725c1 --- /dev/null +++ b/src/prisma/seeder/standard_store/images/dev_profile_images/README.md @@ -0,0 +1,2 @@ +The images are fetched from https://pixabay.com/ +All are free to use, without credits. diff --git a/src/prisma/seeder/standard_store/images/dev_profile_images/Rev.jpg b/src/prisma/seeder/standard_store/images/dev_profile_images/Rev.jpg new file mode 100644 index 000000000..6c6b0e3f1 Binary files /dev/null and b/src/prisma/seeder/standard_store/images/dev_profile_images/Rev.jpg differ diff --git a/src/prisma/seeder/standard_store/images/dev_profile_images/Sjiraff.jpg b/src/prisma/seeder/standard_store/images/dev_profile_images/Sjiraff.jpg new file mode 100644 index 000000000..6b1845c58 Binary files /dev/null and b/src/prisma/seeder/standard_store/images/dev_profile_images/Sjiraff.jpg differ diff --git a/src/prisma/seeder/standard_store/images/dev_profile_images/Skilpadde.jpg b/src/prisma/seeder/standard_store/images/dev_profile_images/Skilpadde.jpg new file mode 100644 index 000000000..2667d7dd1 Binary files /dev/null and b/src/prisma/seeder/standard_store/images/dev_profile_images/Skilpadde.jpg differ diff --git a/src/prisma/seeder/standard_store/images/dev_profile_images/Slange.jpg b/src/prisma/seeder/standard_store/images/dev_profile_images/Slange.jpg new file mode 100644 index 000000000..1df759e4d Binary files /dev/null and b/src/prisma/seeder/standard_store/images/dev_profile_images/Slange.jpg differ diff --git a/src/prisma/seeder/standard_store/images/dev_profile_images/Ugle.jpg b/src/prisma/seeder/standard_store/images/dev_profile_images/Ugle.jpg new file mode 100644 index 000000000..8fe99275c Binary files /dev/null and b/src/prisma/seeder/standard_store/images/dev_profile_images/Ugle.jpg differ diff --git "a/src/prisma/seeder/standard_store/images/dev_profile_images/\303\230rn.jpg" "b/src/prisma/seeder/standard_store/images/dev_profile_images/\303\230rn.jpg" new file mode 100644 index 000000000..57844ea93 Binary files /dev/null and "b/src/prisma/seeder/standard_store/images/dev_profile_images/\303\230rn.jpg" differ