From 8149433067018fa6a4da72fb49f162b3c8c4cbf6 Mon Sep 17 00:00:00 2001 From: Dolu Date: Tue, 6 Sep 2022 13:59:29 +0200 Subject: [PATCH] feat: add HostedImage relation in award, Hackaton, Story and User tables + data migration to HostedImage --- api/functions/graphql/nexus-typegen.ts | 6 -- api/functions/graphql/types/hackathon.js | 13 +++- api/functions/graphql/types/post.js | 25 ++++++- api/functions/graphql/types/tournaments.js | 12 +++- api/functions/graphql/types/users.js | 13 +++- .../migration.sql | 10 --- .../migration.sql | 5 -- .../migration.sql | 40 +++++++++++ prisma/schema.prisma | 72 +++++++++++-------- prisma/seed/index.js | 72 +++++++++++++++++++ 10 files changed, 212 insertions(+), 56 deletions(-) delete mode 100644 prisma/migrations/20220906084958_update_images_to_project_table/migration.sql delete mode 100644 prisma/migrations/20220906090616_update_images_to_category_table/migration.sql create mode 100644 prisma/migrations/20220906115500_update_hosted_image_rel_table/migration.sql diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index 94ec959..838ba43 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -104,7 +104,6 @@ export interface NexusGenObjects { applicants_count: number; // Int! applications: NexusGenRootTypes['BountyApplication'][]; // [BountyApplication!]! body: string; // String! - cover_image?: string | null; // String createdAt: NexusGenScalars['Date']; // Date! deadline: string; // String! excerpt: string; // String! @@ -146,7 +145,6 @@ export interface NexusGenObjects { title: string; // String! } Hackathon: { // root type - cover_image: string; // String! description: string; // String! end_date: NexusGenScalars['Date']; // Date! id: number; // Int! @@ -173,7 +171,6 @@ export interface NexusGenObjects { } Mutation: {}; MyProfile: { // root type - avatar: string; // String! bio?: string | null; // String email?: string | null; // String github?: string | null; // String @@ -220,7 +217,6 @@ export interface NexusGenObjects { } Story: { // root type body: string; // String! - cover_image?: string | null; // String createdAt: NexusGenScalars['Date']; // Date! excerpt: string; // String! id: number; // Int! @@ -237,7 +233,6 @@ export interface NexusGenObjects { title: string; // String! } Tournament: { // root type - cover_image: string; // String! description: string; // String! end_date: NexusGenScalars['Date']; // Date! id: number; // Int! @@ -247,7 +242,6 @@ export interface NexusGenObjects { website: string; // String! } User: { // root type - avatar: string; // String! bio?: string | null; // String email?: string | null; // String github?: string | null; // String diff --git a/api/functions/graphql/types/hackathon.js b/api/functions/graphql/types/hackathon.js index c0b139a..c1eb2e4 100644 --- a/api/functions/graphql/types/hackathon.js +++ b/api/functions/graphql/types/hackathon.js @@ -6,6 +6,7 @@ const { nonNull, } = require('nexus'); const { prisma } = require('../../../prisma'); +const resolveImgObjectToUrl = require('../../../utils/resolveImageUrl'); @@ -15,7 +16,17 @@ const Hackathon = objectType({ t.nonNull.int('id'); t.nonNull.string('title'); t.nonNull.string('description'); - t.nonNull.string('cover_image'); + t.nonNull.string('cover_image', { + async resolve(parent) { + const imgObject = await prisma.hostedImage.findUnique({ + where: { + id: parent.cover_image_id + } + }); + + return resolveImgObjectToUrl(imgObject); + } + }); t.nonNull.date('start_date'); t.nonNull.date('end_date'); t.nonNull.string('location'); diff --git a/api/functions/graphql/types/post.js b/api/functions/graphql/types/post.js index bf04074..d1c8b42 100644 --- a/api/functions/graphql/types/post.js +++ b/api/functions/graphql/types/post.js @@ -15,6 +15,7 @@ const { prisma } = require('../../../prisma'); const { getUserByPubKey } = require('../../../auth/utils/helperFuncs'); const { ApolloError } = require('apollo-server-lambda'); const { marked } = require('marked'); +const resolveImgObjectToUrl = require('../../../utils/resolveImageUrl'); const { ImageInput } = require('./misc'); @@ -72,7 +73,17 @@ const Story = objectType({ t.nonNull.string('type', { resolve: () => t.typeName }); - t.string('cover_image'); + t.string('cover_image', { + async resolve(parent) { + const imgObject = await prisma.hostedImage.findUnique({ + where: { + id: parent.cover_image_id + } + }); + + return resolveImgObjectToUrl(imgObject); + } + }); t.nonNull.list.nonNull.field('comments', { type: "PostComment", resolve: (parent) => [] @@ -140,7 +151,17 @@ const Bounty = objectType({ t.nonNull.string('type', { resolve: () => 'Bounty' }); - t.string('cover_image'); + t.string('cover_image', { + async resolve(parent) { + const imgObject = await prisma.hostedImage.findUnique({ + where: { + id: parent.cover_image_id + } + }); + + return resolveImgObjectToUrl(imgObject); + } + }); t.nonNull.string('deadline'); t.nonNull.int('reward_amount'); t.nonNull.int('applicants_count'); diff --git a/api/functions/graphql/types/tournaments.js b/api/functions/graphql/types/tournaments.js index 9f04081..c7d24f5 100644 --- a/api/functions/graphql/types/tournaments.js +++ b/api/functions/graphql/types/tournaments.js @@ -16,7 +16,17 @@ const Tournament = objectType({ t.nonNull.string('title'); t.nonNull.string('description'); t.nonNull.string('thumbnail_image'); - t.nonNull.string('cover_image'); + t.nonNull.string('cover_image', { + async resolve(parent) { + const imgObject = await prisma.hostedImage.findUnique({ + where: { + id: parent.cover_image_id + } + }); + + return resolveImgObjectToUrl(imgObject); + } + }); t.nonNull.date('start_date'); t.nonNull.date('end_date'); t.nonNull.string('website'); diff --git a/api/functions/graphql/types/users.js b/api/functions/graphql/types/users.js index ae05df8..656e815 100644 --- a/api/functions/graphql/types/users.js +++ b/api/functions/graphql/types/users.js @@ -5,6 +5,7 @@ const { getUserByPubKey } = require("../../../auth/utils/helperFuncs"); const { removeNulls } = require("./helpers"); const { ImageInput } = require('./misc'); const { Tournament } = require('./tournaments'); +const resolveImgObjectToUrl = require('../../../utils/resolveImageUrl'); @@ -14,7 +15,17 @@ const BaseUser = interfaceType({ definition(t) { t.nonNull.int('id'); t.nonNull.string('name'); - t.nonNull.string('avatar'); + t.nonNull.string('avatar', { + async resolve(parent) { + const imgObject = await prisma.hostedImage.findUnique({ + where: { + id: parent.avatar_id + } + }); + + return resolveImgObjectToUrl(imgObject); + } + }); t.nonNull.date('join_date'); t.string('role'); t.string('email') diff --git a/prisma/migrations/20220906084958_update_images_to_project_table/migration.sql b/prisma/migrations/20220906084958_update_images_to_project_table/migration.sql deleted file mode 100644 index d1f16d4..0000000 --- a/prisma/migrations/20220906084958_update_images_to_project_table/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ --- AlterTable -ALTER TABLE "Project" ADD COLUMN "cover_image_id" INTEGER, -ADD COLUMN "screenshots_ids" INTEGER[], -ADD COLUMN "thumbnail_image_id" INTEGER; - --- AddForeignKey -ALTER TABLE "Project" ADD CONSTRAINT "Project_thumbnail_image_id_fkey" FOREIGN KEY ("thumbnail_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Project" ADD CONSTRAINT "Project_cover_image_id_fkey" FOREIGN KEY ("cover_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20220906090616_update_images_to_category_table/migration.sql b/prisma/migrations/20220906090616_update_images_to_category_table/migration.sql deleted file mode 100644 index be7a3ae..0000000 --- a/prisma/migrations/20220906090616_update_images_to_category_table/migration.sql +++ /dev/null @@ -1,5 +0,0 @@ --- AlterTable -ALTER TABLE "Category" ADD COLUMN "cover_image_id" INTEGER; - --- AddForeignKey -ALTER TABLE "Category" ADD CONSTRAINT "Category_cover_image_id_fkey" FOREIGN KEY ("cover_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20220906115500_update_hosted_image_rel_table/migration.sql b/prisma/migrations/20220906115500_update_hosted_image_rel_table/migration.sql new file mode 100644 index 0000000..eb4120a --- /dev/null +++ b/prisma/migrations/20220906115500_update_hosted_image_rel_table/migration.sql @@ -0,0 +1,40 @@ +-- AlterTable +ALTER TABLE "Award" ADD COLUMN "image_id" INTEGER; + +-- AlterTable +ALTER TABLE "Category" ADD COLUMN "cover_image_id" INTEGER; + +-- AlterTable +ALTER TABLE "Hackathon" ADD COLUMN "cover_image_id" INTEGER; + +-- AlterTable +ALTER TABLE "Project" ADD COLUMN "cover_image_id" INTEGER, +ADD COLUMN "screenshots_ids" INTEGER[], +ADD COLUMN "thumbnail_image_id" INTEGER; + +-- AlterTable +ALTER TABLE "Story" ADD COLUMN "cover_image_id" INTEGER; + +-- AlterTable +ALTER TABLE "User" ADD COLUMN "avatar_id" INTEGER; + +-- AddForeignKey +ALTER TABLE "User" ADD CONSTRAINT "User_avatar_id_fkey" FOREIGN KEY ("avatar_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Category" ADD CONSTRAINT "Category_cover_image_id_fkey" FOREIGN KEY ("cover_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Project" ADD CONSTRAINT "Project_thumbnail_image_id_fkey" FOREIGN KEY ("thumbnail_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Project" ADD CONSTRAINT "Project_cover_image_id_fkey" FOREIGN KEY ("cover_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Award" ADD CONSTRAINT "Award_image_id_fkey" FOREIGN KEY ("image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Story" ADD CONSTRAINT "Story_cover_image_id_fkey" FOREIGN KEY ("cover_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Hackathon" ADD CONSTRAINT "Hackathon_cover_image_id_fkey" FOREIGN KEY ("cover_image_id") REFERENCES "HostedImage"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 733125f..b5b8d3b 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -40,11 +40,13 @@ model Vote { // ----------------- model User { - id Int @id @default(autoincrement()) - pubKey String? @unique - name String? - avatar String? - role String @default("user") + id Int @id @default(autoincrement()) + pubKey String? @unique + name String? + avatar String? + avatar_id Int? + avatar_rel HostedImage? @relation("UserAvatar", fields: [avatar_id], references: [id]) + role String @default("user") email String? jobTitle String? @@ -162,10 +164,12 @@ model ProjectRecruitRoles { } model Award { - id Int @id @default(autoincrement()) - title String - image String - url String + id Int @id @default(autoincrement()) + title String + image String + image_id Int? + image_rel HostedImage? @relation("AwardImage", fields: [image_id], references: [id]) + url String project Project @relation(fields: [project_id], references: [id]) project_id Int @@ -176,15 +180,17 @@ model Award { // ----------------- model Story { - id Int @id @default(autoincrement()) - title String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - body String - excerpt String - cover_image String? - votes_count Int @default(0) - is_published Boolean @default(true) + id Int @id @default(autoincrement()) + title String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + body String + excerpt String + cover_image String? + cover_image_id Int? + cover_image_rel HostedImage? @relation("StoryCoverImage", fields: [cover_image_id], references: [id]) + votes_count Int @default(0) + is_published Boolean @default(true) tags Tag[] @@ -237,15 +243,17 @@ model PostComment { // Hackathons // ----------------- model Hackathon { - id Int @id @default(autoincrement()) - title String - start_date DateTime @db.Date - end_date DateTime @db.Date - cover_image String - description String - location String - website String - votes_count Int @default(0) + id Int @id @default(autoincrement()) + title String + start_date DateTime @db.Date + end_date DateTime @db.Date + cover_image String + cover_image_id Int? + cover_image_rel HostedImage? @relation("HackathonCoverImage", fields: [cover_image_id], references: [id]) + description String + location String + website String + votes_count Int @default(0) tags Tag[] } @@ -287,9 +295,13 @@ model HostedImage { createdAt DateTime @default(now()) is_used Boolean @default(false) - ProjectThumbnail Project[] @relation("ProjectThumbnail") - ProjectCoverImage Project[] @relation("ProjectCoverImage") - CategoryCoverImage Category[] @relation("CategoryCoverImage") + ProjectThumbnail Project[] @relation("ProjectThumbnail") + ProjectCoverImage Project[] @relation("ProjectCoverImage") + CategoryCoverImage Category[] @relation("CategoryCoverImage") + AwardImage Award[] @relation("AwardImage") + HackathonCoverImage Hackathon[] @relation("HackathonCoverImage") + StoryCoverImage Story[] @relation("StoryCoverImage") + User User[] @relation("UserAvatar") } // ----------------- diff --git a/prisma/seed/index.js b/prisma/seed/index.js index f471a76..f6ae9be 100644 --- a/prisma/seed/index.js +++ b/prisma/seed/index.js @@ -136,6 +136,78 @@ async function migrateOldImages() { }) } } + + /** + * Award + **/ + const awards = await prisma.award.findMany({ + select: { + id: true, + image: true, + } + }) + for (const award of awards) { + if (award.image) { + let hostedImageId = await _insertInHostedImage(award.image) + await _updateObjectWithHostedImageId(prisma.award, award.id, { + image_id: hostedImageId, + }) + } + } + + /** + * Hackaton + **/ + const hackatons = await prisma.hackathon.findMany({ + select: { + id: true, + cover_image: true, + } + }) + for (const hackaton of hackatons) { + if (hackaton.cover_image) { + let hostedImageId = await _insertInHostedImage(hackaton.cover_image) + await _updateObjectWithHostedImageId(prisma.hackathon, hackaton.id, { + cover_image_id: hostedImageId, + }) + } + } + + /** + * Story + **/ + const stories = await prisma.story.findMany({ + select: { + id: true, + cover_image: true, + } + }) + for (const story of stories) { + if (story.cover_image) { + let hostedImageId = await _insertInHostedImage(story.cover_image) + await _updateObjectWithHostedImageId(prisma.story, story.id, { + cover_image_id: hostedImageId, + }) + } + } + + /** + * User + **/ + const users = await prisma.user.findMany({ + select: { + id: true, + avatar: true, + } + }) + for (const user of users) { + if (user.avatar) { + let hostedImageId = await _insertInHostedImage(user.avatar) + await _updateObjectWithHostedImageId(prisma.user, user.id, { + avatar_id: hostedImageId, + }) + } + } } async function _insertInHostedImage(url){