update: db schema to include imgs-uploading feature

This commit is contained in:
MTG2000
2022-09-13 12:00:59 +03:00
parent 5b263aca01
commit 39cc248fba
4 changed files with 359 additions and 45 deletions

View File

@@ -0,0 +1,29 @@
/*
Warnings:
- The primary key for the `HostedImage` table will be changed. If it partially fails, the table could be left without primary key constraint.
- The `id` column on the `HostedImage` table would be dropped and recreated. This will lead to data loss if there is data in the column.
- Added the required column `provider` to the `HostedImage` table without a default value. This is not possible if the table is not empty.
- Added the required column `provider_image_id` to the `HostedImage` table without a default value. This is not possible if the table is not empty.
- Added the required column `url` to the `HostedImage` table without a default value. This is not possible if the table is not empty.
*/
-- START Custom SQL
-- Because of the breaking changes, we have to apply some custom SQL.
-- By chance, the previous HostedImage migration is not used it production, so we can remove all data from this table
DELETE FROM "HostedImage";
-- END Custom SQL
-- AlterTable
ALTER TABLE "HostedImage" DROP CONSTRAINT "HostedImage_pkey",
ADD COLUMN "provider" TEXT NOT NULL,
ADD COLUMN "provider_image_id" TEXT NOT NULL,
ADD COLUMN "url" TEXT NOT NULL,
DROP COLUMN "id",
ADD COLUMN "id" SERIAL NOT NULL,
ADD CONSTRAINT "HostedImage_pkey" PRIMARY KEY ("id");
-- AlterTable
ALTER TABLE "UserKey" ALTER COLUMN "name" SET DEFAULT E'My new wallet key';

View File

@@ -0,0 +1,74 @@
/*
Warnings:
- A unique constraint covering the columns `[image_id]` on the table `Award` will be added. If there are existing duplicate values, this will fail.
- A unique constraint covering the columns `[cover_image_id]` on the table `Category` will be added. If there are existing duplicate values, this will fail.
- A unique constraint covering the columns `[cover_image_id]` on the table `Hackathon` will be added. If there are existing duplicate values, this will fail.
- A unique constraint covering the columns `[thumbnail_image_id]` on the table `Project` will be added. If there are existing duplicate values, this will fail.
- A unique constraint covering the columns `[cover_image_id]` on the table `Project` will be added. If there are existing duplicate values, this will fail.
- A unique constraint covering the columns `[cover_image_id]` on the table `Story` will be added. If there are existing duplicate values, this will fail.
- A unique constraint covering the columns `[avatar_id]` on the table `User` will be added. If there are existing duplicate values, this will fail.
*/
-- 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 "body_image_ids" INTEGER[],
ADD COLUMN "cover_image_id" INTEGER;
-- AlterTable
ALTER TABLE "User" ADD COLUMN "avatar_id" INTEGER;
-- CreateIndex
CREATE UNIQUE INDEX "Award_image_id_key" ON "Award"("image_id");
-- CreateIndex
CREATE UNIQUE INDEX "Category_cover_image_id_key" ON "Category"("cover_image_id");
-- CreateIndex
CREATE UNIQUE INDEX "Hackathon_cover_image_id_key" ON "Hackathon"("cover_image_id");
-- CreateIndex
CREATE UNIQUE INDEX "Project_thumbnail_image_id_key" ON "Project"("thumbnail_image_id");
-- CreateIndex
CREATE UNIQUE INDEX "Project_cover_image_id_key" ON "Project"("cover_image_id");
-- CreateIndex
CREATE UNIQUE INDEX "Story_cover_image_id_key" ON "Story"("cover_image_id");
-- CreateIndex
CREATE UNIQUE INDEX "User_avatar_id_key" ON "User"("avatar_id");
-- 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;

View File

@@ -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? @unique
avatar_rel HostedImage? @relation("User_Avatar", fields: [avatar_id], references: [id])
role String @default("user")
email String?
jobTitle String?
@@ -112,24 +114,31 @@ model Skill {
// -----------------
model Category {
id Int @id @default(autoincrement())
title String
cover_image String?
icon String?
id Int @id @default(autoincrement())
title String
cover_image String?
cover_image_id Int? @unique
cover_image_rel HostedImage? @relation("Category_CoverImage", fields: [cover_image_id], references: [id])
icon String?
project Project[]
}
model Project {
id Int @id @default(autoincrement())
title String
description String
screenshots String[]
website String
thumbnail_image String?
cover_image String?
lightning_address String?
lnurl_callback_url String?
id Int @id @default(autoincrement())
title String
description String
screenshots String[]
screenshots_ids Int[]
website String
thumbnail_image String?
thumbnail_image_id Int? @unique
thumbnail_image_rel HostedImage? @relation("Project_Thumbnail", fields: [thumbnail_image_id], references: [id])
cover_image String?
cover_image_id Int? @unique
cover_image_rel HostedImage? @relation("Project_CoverImage", fields: [cover_image_id], references: [id])
lightning_address String?
lnurl_callback_url String?
category Category @relation(fields: [category_id], references: [id])
category_id Int
@@ -155,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? @unique
image_rel HostedImage? @relation("Award_Image", fields: [image_id], references: [id])
url String
project Project @relation(fields: [project_id], references: [id])
project_id Int
@@ -169,15 +180,18 @@ 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
body_image_ids Int[]
excerpt String
cover_image String?
cover_image_id Int? @unique
cover_image_rel HostedImage? @relation("Story_CoverImage", fields: [cover_image_id], references: [id])
votes_count Int @default(0)
is_published Boolean @default(true)
tags Tag[]
@@ -230,15 +244,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? @unique
cover_image_rel HostedImage? @relation("Hackathon_CoverImage", fields: [cover_image_id], references: [id])
description String
location String
website String
votes_count Int @default(0)
tags Tag[]
}
@@ -272,10 +288,21 @@ model GeneratedK1 {
// Hosted Image
// -----------------
model HostedImage {
id String @id
filename String
createdAt DateTime @default(now())
is_used Boolean @default(false)
id Int @id @default(autoincrement())
filename String
provider_image_id String
provider String
url String
createdAt DateTime @default(now())
is_used Boolean @default(false)
ProjectThumbnail Project? @relation("Project_Thumbnail")
ProjectCoverImage Project? @relation("Project_CoverImage")
CategoryCoverImage Category? @relation("Category_CoverImage")
AwardImage Award? @relation("Award_Image")
HackathonCoverImage Hackathon? @relation("Hackathon_CoverImage")
StoryCoverImage Story? @relation("Story_CoverImage")
User User? @relation("User_Avatar")
}
// -----------------

View File

@@ -65,8 +65,192 @@ async function main() {
// await createSkills();
await createTournament();
// await createTournament();
await migrateOldImages();
}
async function migrateOldImages() {
console.log('Migrating old images data to HostedImage');
// Can't use prisma method createMany() for columns like Project.screenshots, because this method doesn't return created IDs.
/**
* Project
**/
const projects = await prisma.project.findMany({
select: {
id: true,
screenshots: true,
cover_image: true,
thumbnail_image: true
}
})
for (const project of projects) {
/**
* Project.screenshots to Project.screenshots_ids
**/
let projectScreenshotIds = [];
for (const screenshot of project.screenshots) {
let hostedImageId = await _insertInHostedImage(screenshot)
projectScreenshotIds.push(hostedImageId);
}
if (projectScreenshotIds.length > 0) {
await _updateObjectWithHostedImageId(prisma.project, project.id, {
screenshots_ids: projectScreenshotIds,
})
}
/**
* Project.cover_image to Project.cover_image_id
**/
if (project.cover_image) {
let hostedImageId = await _insertInHostedImage(project.cover_image)
await _updateObjectWithHostedImageId(prisma.project, project.id, {
cover_image_id: hostedImageId,
})
}
/**
* Project.thumbnail_image to Project.thumbnail_image_id
**/
if (project.cover_image) {
let hostedImageId = await _insertInHostedImage(project.thumbnail_image)
await _updateObjectWithHostedImageId(prisma.project, project.id, {
thumbnail_image_id: hostedImageId,
})
}
}
/**
* Category
**/
const categories = await prisma.category.findMany({
select: {
id: true,
cover_image: true,
}
})
for (const category of categories) {
if (category.cover_image) {
let hostedImageId = await _insertInHostedImage(category.cover_image)
await _updateObjectWithHostedImageId(prisma.category, category.id, {
cover_image_id: hostedImageId,
})
}
}
/**
* 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,
body: true,
}
})
for (const story of stories) {
/**
* Story.body to Story.body_image_ids
**/
let bodyImageIds = [];
const regex = /(?:!\[(.*?)\]\((.*?)\))/g
let match;
while ((match = regex.exec(story.body))) {
const [, , value] = match
let hostedImageId = await _insertInHostedImage(value)
bodyImageIds.push(hostedImageId)
}
if (bodyImageIds.length > 0) {
await _updateObjectWithHostedImageId(prisma.story, story.id, {
body_image_ids: bodyImageIds,
})
}
/**
* Story.cover_image to Story.cover_image_id
**/
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) {
const newHostedImage = await prisma.hostedImage.create({
data: {
filename: "default.png",
provider: "external",
provider_image_id: "",
url,
is_used: true
}
});
return newHostedImage.id;
}
async function _updateObjectWithHostedImageId(prismaObject, objectId, data) {
await prismaObject.update({
where: { id: objectId },
data,
});
}
async function createCategories() {