mirror of
https://github.com/aljazceru/landscape-template.git
synced 2025-12-18 14:54:23 +01:00
feat: add image management for stories and user avatar
This commit is contained in:
@@ -88,7 +88,6 @@ export interface NexusGenScalars {
|
||||
|
||||
export interface NexusGenObjects {
|
||||
Author: { // root type
|
||||
avatar: string; // String!
|
||||
id: number; // Int!
|
||||
join_date: NexusGenScalars['Date']; // Date!
|
||||
lightning_address?: string | null; // String
|
||||
|
||||
@@ -5,7 +5,7 @@ const {
|
||||
nonNull,
|
||||
} = require('nexus');
|
||||
const { prisma } = require('../../../prisma');
|
||||
const resolveImgObjectToUrl = require('../../../utils/resolveImageUrl');
|
||||
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
|
||||
|
||||
|
||||
const Category = objectType({
|
||||
@@ -15,6 +15,7 @@ const Category = objectType({
|
||||
t.nonNull.string('title');
|
||||
t.string('cover_image', {
|
||||
async resolve(parent) {
|
||||
if (!parent.cover_image_id) return null
|
||||
const imgObject = await prisma.hostedImage.findUnique({
|
||||
where: {
|
||||
id: parent.cover_image_id
|
||||
|
||||
@@ -6,7 +6,7 @@ const {
|
||||
nonNull,
|
||||
} = require('nexus');
|
||||
const { prisma } = require('../../../prisma');
|
||||
const resolveImgObjectToUrl = require('../../../utils/resolveImageUrl');
|
||||
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ const Hackathon = objectType({
|
||||
t.nonNull.string('description');
|
||||
t.nonNull.string('cover_image', {
|
||||
async resolve(parent) {
|
||||
if (!parent.cover_image_id) return null
|
||||
const imgObject = await prisma.hostedImage.findUnique({
|
||||
where: {
|
||||
id: parent.cover_image_id
|
||||
|
||||
@@ -15,8 +15,9 @@ 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 { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
|
||||
const { ImageInput } = require('./misc');
|
||||
const { deleteImage } = require('../../../services/imageUpload.service');
|
||||
|
||||
|
||||
const POST_TYPE = enumType({
|
||||
@@ -39,7 +40,17 @@ const Author = objectType({
|
||||
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('lightning_address');
|
||||
@@ -75,6 +86,7 @@ const Story = objectType({
|
||||
});
|
||||
t.string('cover_image', {
|
||||
async resolve(parent) {
|
||||
if (!parent.cover_image_id) return null
|
||||
const imgObject = await prisma.hostedImage.findUnique({
|
||||
where: {
|
||||
id: parent.cover_image_id
|
||||
@@ -153,6 +165,7 @@ const Bounty = objectType({
|
||||
});
|
||||
t.string('cover_image', {
|
||||
async resolve(parent) {
|
||||
if (!parent.cover_image_id) return null
|
||||
const imgObject = await prisma.hostedImage.findUnique({
|
||||
where: {
|
||||
id: parent.cover_image_id
|
||||
@@ -366,6 +379,64 @@ const getPostById = extendType({
|
||||
}
|
||||
})
|
||||
|
||||
const addCoverImage = async (providerImageId) => {
|
||||
const newCoverImage = await prisma.hostedImage.findFirst({
|
||||
where: {
|
||||
provider_image_id: providerImageId
|
||||
}
|
||||
})
|
||||
|
||||
if (!newCoverImage) throw new ApolloError("New cover image not found")
|
||||
|
||||
await prisma.hostedImage.update({
|
||||
where: {
|
||||
id: newCoverImage.id
|
||||
},
|
||||
data: {
|
||||
is_used: true
|
||||
}
|
||||
})
|
||||
|
||||
return newCoverImage
|
||||
}
|
||||
|
||||
const getHostedImageIdsFromBody = async (body, oldBodyImagesIds = null) => {
|
||||
let bodyImageIds = []
|
||||
|
||||
const regex = /(?:!\[(.*?)\]\((.*?)\))/g
|
||||
let match;
|
||||
while((match = regex.exec(body))) {
|
||||
const [,,value] = match
|
||||
|
||||
// Useful for old external images in case of duplicates. We need to be sure we are targeting an image from the good story.
|
||||
const where = oldBodyImagesIds ? {
|
||||
AND: [
|
||||
{ url: value },
|
||||
{ id: { in: oldBodyImagesIds } }
|
||||
]
|
||||
} :
|
||||
{
|
||||
url: value,
|
||||
}
|
||||
|
||||
const hostedImage = await prisma.hostedImage.findFirst({
|
||||
where
|
||||
})
|
||||
if (hostedImage) {
|
||||
bodyImageIds.push(hostedImage.id)
|
||||
await prisma.hostedImage.update({
|
||||
where: {
|
||||
id: hostedImage.id
|
||||
},
|
||||
data: {
|
||||
is_used: true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return bodyImageIds
|
||||
}
|
||||
|
||||
const createStory = extendType({
|
||||
type: 'Mutation',
|
||||
definition(t) {
|
||||
@@ -382,20 +453,64 @@ const createStory = extendType({
|
||||
|
||||
let was_published = false;
|
||||
|
||||
|
||||
// TODO: validate post data
|
||||
|
||||
let coverImage = null
|
||||
let bodyImageIds = []
|
||||
|
||||
// Edit story
|
||||
if (id) {
|
||||
const oldPost = await prisma.story.findFirst({
|
||||
where: { id },
|
||||
select: {
|
||||
user_id: true,
|
||||
is_published: true
|
||||
is_published: true,
|
||||
cover_image_id: true,
|
||||
body_image_ids: true
|
||||
}
|
||||
})
|
||||
was_published = oldPost.is_published;
|
||||
if (user.id !== oldPost.user_id)
|
||||
throw new ApolloError("Not post author")
|
||||
}
|
||||
// TODO: validate post data
|
||||
if (user.id !== oldPost.user_id) throw new ApolloError("Not post author")
|
||||
|
||||
// Body images
|
||||
bodyImageIds = await getHostedImageIdsFromBody(body, oldPost.body_image_ids)
|
||||
|
||||
// Old cover image is found
|
||||
if (oldPost.cover_image_id) {
|
||||
const oldCoverImage = await prisma.hostedImage.findFirst({
|
||||
where : {
|
||||
id: oldPost.cover_image_id
|
||||
}
|
||||
})
|
||||
|
||||
// New cover image
|
||||
if (cover_image?.id && cover_image.id !== oldCoverImage?.provider_image_id) {
|
||||
await deleteImage(oldCoverImage.id)
|
||||
coverImage = await addCoverImage(cover_image.id)
|
||||
} else {
|
||||
coverImage = oldCoverImage
|
||||
}
|
||||
} else {
|
||||
// No old image found and new cover image
|
||||
if (cover_image?.id) {
|
||||
coverImage = await addCoverImage(cover_image.id)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove unused body images
|
||||
const unusedImagesIds = oldPost.body_image_ids.filter(x => !bodyImageIds.includes(x));
|
||||
unusedImagesIds.map(async i => await deleteImage(i))
|
||||
|
||||
} else {
|
||||
// Body images
|
||||
bodyImageIds = await getHostedImageIdsFromBody(body)
|
||||
|
||||
// New story and new cover image
|
||||
if (cover_image?.id) {
|
||||
coverImage = await addCoverImage(cover_image.id)
|
||||
}
|
||||
}
|
||||
|
||||
// Preprocess & insert
|
||||
const htmlBody = marked.parse(body);
|
||||
@@ -408,12 +523,14 @@ const createStory = extendType({
|
||||
;
|
||||
|
||||
|
||||
// ----------------
|
||||
// Check the uploaded cover image & the images in the body,
|
||||
// remove the old one from the hosting service, then replace it with these ones
|
||||
// ----------------
|
||||
|
||||
|
||||
const coverImageRel = coverImage ? {
|
||||
cover_image_rel: {
|
||||
connect:
|
||||
{
|
||||
id: coverImage ? coverImage.id : null
|
||||
}
|
||||
}
|
||||
} : {}
|
||||
|
||||
if (id) {
|
||||
await prisma.story.update({
|
||||
@@ -430,7 +547,7 @@ const createStory = extendType({
|
||||
data: {
|
||||
title,
|
||||
body,
|
||||
cover_image: cover_image.url,
|
||||
cover_image: '',
|
||||
excerpt,
|
||||
is_published: was_published || is_published,
|
||||
tags: {
|
||||
@@ -447,16 +564,17 @@ const createStory = extendType({
|
||||
}
|
||||
})
|
||||
},
|
||||
body_image_ids: bodyImageIds,
|
||||
...coverImageRel
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
return prisma.story.create({
|
||||
return await prisma.story.create({
|
||||
data: {
|
||||
title,
|
||||
body,
|
||||
cover_image: cover_image.url,
|
||||
cover_image: '',
|
||||
excerpt,
|
||||
is_published,
|
||||
tags: {
|
||||
@@ -477,7 +595,9 @@ const createStory = extendType({
|
||||
connect: {
|
||||
id: user.id,
|
||||
}
|
||||
}
|
||||
},
|
||||
body_image_ids: bodyImageIds,
|
||||
...coverImageRel
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -502,17 +622,39 @@ const deleteStory = extendType({
|
||||
const oldPost = await prisma.story.findFirst({
|
||||
where: { id },
|
||||
select: {
|
||||
user_id: true
|
||||
user_id: true,
|
||||
body_image_ids: true,
|
||||
cover_image_id: true
|
||||
}
|
||||
})
|
||||
if (user.id !== oldPost.user_id)
|
||||
throw new ApolloError("Not post author")
|
||||
|
||||
return prisma.story.delete({
|
||||
const deletedPost = await prisma.story.delete({
|
||||
where: {
|
||||
id
|
||||
}
|
||||
})
|
||||
|
||||
const coverImage = await prisma.hostedImage.findMany({
|
||||
where: {
|
||||
OR: [
|
||||
{ id: oldPost.cover_image_id },
|
||||
{
|
||||
id: {
|
||||
in: oldPost.body_image_ids
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
provider_image_id: true
|
||||
}
|
||||
})
|
||||
coverImage.map(async i => await deleteImage(i.id))
|
||||
|
||||
return deletedPost
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@ const {
|
||||
nonNull,
|
||||
} = require('nexus')
|
||||
const { prisma } = require('../../../prisma');
|
||||
const resolveImgObjectToUrl = require('../../../utils/resolveImageUrl');
|
||||
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
|
||||
|
||||
const { paginationArgs, getLnurlDetails, lightningAddressToLnurl } = require('./helpers');
|
||||
const { MakerRole } = require('./users');
|
||||
@@ -20,6 +20,7 @@ const Project = objectType({
|
||||
t.nonNull.string('description');
|
||||
t.nonNull.string('cover_image', {
|
||||
async resolve(parent) {
|
||||
if (!parent.cover_image_id) return null
|
||||
const imgObject = await prisma.hostedImage.findUnique({
|
||||
where: {
|
||||
id: parent.cover_image_id
|
||||
@@ -31,6 +32,7 @@ const Project = objectType({
|
||||
});
|
||||
t.nonNull.string('thumbnail_image', {
|
||||
async resolve(parent) {
|
||||
if (!parent.thumbnail_image_id) return null
|
||||
const imgObject = await prisma.hostedImage.findUnique({
|
||||
where: {
|
||||
id: parent.thumbnail_image_id
|
||||
@@ -42,6 +44,7 @@ const Project = objectType({
|
||||
});
|
||||
t.nonNull.list.nonNull.string('screenshots', {
|
||||
async resolve(parent) {
|
||||
if (!parent.screenshots_ids) return null
|
||||
const imgObject = await prisma.hostedImage.findMany({
|
||||
where: {
|
||||
id: { in: parent.screenshots_ids }
|
||||
|
||||
@@ -6,6 +6,7 @@ const {
|
||||
nonNull,
|
||||
} = require('nexus');
|
||||
const { prisma } = require('../../../prisma');
|
||||
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +19,7 @@ const Tournament = objectType({
|
||||
t.nonNull.string('thumbnail_image');
|
||||
t.nonNull.string('cover_image', {
|
||||
async resolve(parent) {
|
||||
if (!parent.cover_image_id) return null
|
||||
const imgObject = await prisma.hostedImage.findUnique({
|
||||
where: {
|
||||
id: parent.cover_image_id
|
||||
|
||||
@@ -5,7 +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');
|
||||
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
|
||||
const { deleteImage } = require('../../../services/imageUpload.service');
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ const BaseUser = interfaceType({
|
||||
t.nonNull.string('name');
|
||||
t.nonNull.string('avatar', {
|
||||
async resolve(parent) {
|
||||
if (!parent.avatar_id) return null
|
||||
const imgObject = await prisma.hostedImage.findUnique({
|
||||
where: {
|
||||
id: parent.avatar_id
|
||||
@@ -301,15 +302,6 @@ const updateProfileDetails = extendType({
|
||||
if (newAvatar && newAvatar.id !== user.avatar_id) {
|
||||
avatarId = newAvatar.id;
|
||||
|
||||
// Set is_used to false in case of deleteImage() fail. The scheduled job will try to delete the HostedImage row
|
||||
await prisma.hostedImage.update({
|
||||
where: {
|
||||
id: user.avatar_id
|
||||
},
|
||||
data: {
|
||||
is_used: false
|
||||
}
|
||||
});
|
||||
await prisma.hostedImage.update({
|
||||
where: {
|
||||
id: newAvatar.id
|
||||
@@ -319,7 +311,7 @@ const updateProfileDetails = extendType({
|
||||
}
|
||||
});
|
||||
|
||||
deleteImage(user.avatar_id)
|
||||
await deleteImage(user.avatar_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user