mirror of
https://github.com/aljazceru/landscape-template.git
synced 2026-01-31 12:14:30 +01:00
feat: add HostedImage relation in Project table + data migration to HostedImage
This commit is contained in:
@@ -200,13 +200,10 @@ export interface NexusGenObjects {
|
||||
votes_count: number; // Int!
|
||||
}
|
||||
Project: { // root type
|
||||
cover_image: string; // String!
|
||||
description: string; // String!
|
||||
id: number; // Int!
|
||||
lightning_address?: string | null; // String
|
||||
lnurl_callback_url?: string | null; // String
|
||||
screenshots: string[]; // [String!]!
|
||||
thumbnail_image: string; // String!
|
||||
title: string; // String!
|
||||
votes_count: number; // Int!
|
||||
website: string; // String!
|
||||
|
||||
@@ -6,6 +6,7 @@ const {
|
||||
nonNull,
|
||||
} = require('nexus')
|
||||
const { prisma } = require('../../../prisma');
|
||||
const resolveImgObjectToUrl = require('../../../utils/resolveImageUrl');
|
||||
|
||||
const { paginationArgs, getLnurlDetails, lightningAddressToLnurl } = require('./helpers');
|
||||
const { MakerRole } = require('./users');
|
||||
@@ -17,9 +18,41 @@ const Project = objectType({
|
||||
t.nonNull.int('id');
|
||||
t.nonNull.string('title');
|
||||
t.nonNull.string('description');
|
||||
t.nonNull.string('cover_image');
|
||||
t.nonNull.string('thumbnail_image');
|
||||
t.nonNull.list.nonNull.string('screenshots');
|
||||
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.string('thumbnail_image', {
|
||||
async resolve(parent) {
|
||||
const imgObject = await prisma.hostedImage.findUnique({
|
||||
where: {
|
||||
id: parent.thumbnail_image_id
|
||||
}
|
||||
});
|
||||
|
||||
return resolveImgObjectToUrl(imgObject);
|
||||
}
|
||||
});
|
||||
t.nonNull.list.nonNull.string('screenshots', {
|
||||
async resolve(parent) {
|
||||
const imgObject = await prisma.hostedImage.findMany({
|
||||
where: {
|
||||
id: { in: parent.screenshots_ids }
|
||||
}
|
||||
});
|
||||
|
||||
return imgObject.map(img => {
|
||||
return resolveImgObjectToUrl(img);
|
||||
});
|
||||
}
|
||||
});
|
||||
t.nonNull.string('website');
|
||||
t.string('lightning_address');
|
||||
t.string('lnurl_callback_url');
|
||||
|
||||
@@ -22,11 +22,11 @@ const postUploadImageUrl = async (req, res) => {
|
||||
try {
|
||||
const uploadUrl = await getDirectUploadUrl()
|
||||
|
||||
await prisma.hostedImage.create({
|
||||
data: { id: uploadUrl.id, filename },
|
||||
const hostedImage = await prisma.hostedImage.create({
|
||||
data: { filename },
|
||||
})
|
||||
|
||||
return res.status(200).json(uploadUrl)
|
||||
return res.status(200).json({ id: hostedImage.id, uploadUrl: uploadUrl.uploadUrl })
|
||||
} catch (error) {
|
||||
res.status(500).send('Unexpected error happened, please try again')
|
||||
}
|
||||
|
||||
10
api/utils/resolveImageUrl.js
Normal file
10
api/utils/resolveImageUrl.js
Normal file
@@ -0,0 +1,10 @@
|
||||
function resolveImgObjectToUrl(imgObject) {
|
||||
if(imgObject && imgObject.provider === 'external'){
|
||||
return imgObject.url;
|
||||
}
|
||||
else {
|
||||
return "TODO";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = resolveImgObjectToUrl;
|
||||
365
package-lock.json
generated
365
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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';
|
||||
@@ -0,0 +1,10 @@
|
||||
-- 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;
|
||||
@@ -121,15 +121,20 @@ model Category {
|
||||
}
|
||||
|
||||
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?
|
||||
thumbnail_image_rel HostedImage? @relation("ProjectThumbnail", fields: [thumbnail_image_id], references: [id])
|
||||
cover_image String?
|
||||
cover_image_id Int?
|
||||
cover_image_rel HostedImage? @relation("ProjectCoverImage", fields: [cover_image_id], references: [id])
|
||||
lightning_address String?
|
||||
lnurl_callback_url String?
|
||||
|
||||
category Category @relation(fields: [category_id], references: [id])
|
||||
category_id Int
|
||||
@@ -272,10 +277,16 @@ 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("ProjectThumbnail")
|
||||
ProjectCoverImage Project[] @relation("ProjectCoverImage")
|
||||
}
|
||||
|
||||
// -----------------
|
||||
|
||||
@@ -64,6 +64,79 @@ async function main() {
|
||||
|
||||
// await createSkills();
|
||||
|
||||
// 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,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
Reference in New Issue
Block a user