Merge branch 'dev' into feature/list-your-product-ui

This commit is contained in:
MTG2000
2022-09-19 10:50:24 +03:00
5 changed files with 277 additions and 111 deletions

View File

@@ -18,6 +18,7 @@ const { marked } = require('marked');
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
const { ImageInput } = require('./misc');
const { deleteImage } = require('../../../services/imageUpload.service');
const { logError } = require('../../../utils/logger');
const POST_TYPE = enumType({
@@ -435,97 +436,129 @@ const createStory = extendType({
let coverImage = null
let bodyImageIds = []
// Edit story
if (id) {
const oldPost = await prisma.story.findFirst({
where: { id },
select: {
user_id: 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")
// 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
try {
if (id) {
const oldPost = await prisma.story.findFirst({
where: { id },
select: {
user_id: 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")
// New cover image
if (cover_image?.id && cover_image.id !== oldCoverImage?.provider_image_id) {
await deleteImage(oldCoverImage.id)
coverImage = await addCoverImage(cover_image.id)
// 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 {
coverImage = oldCoverImage
// 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 {
// No old image found and new cover image
// Body images
bodyImageIds = await getHostedImageIdsFromBody(body)
// New story 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);
const excerpt = htmlBody
.replace(/<[^>]+>/g, '')
.slice(0, 120)
.replace(/&amp;/g, "&")
.replace(/&#39;/g, "'")
.replace(/&quot;/g, '"')
;
// Preprocess & insert
const htmlBody = marked.parse(body);
const excerpt = htmlBody
.replace(/<[^>]+>/g, '')
.slice(0, 120)
.replace(/&amp;/g, "&")
.replace(/&#39;/g, "'")
.replace(/&quot;/g, '"')
;
const coverImageRel = coverImage ? {
cover_image_rel: {
connect:
{
id: coverImage ? coverImage.id : null
const coverImageRel = coverImage ? {
cover_image_rel: {
connect:
{
id: coverImage ? coverImage.id : null
}
}
} : {}
if (id) {
await prisma.story.update({
where: { id },
data: {
tags: {
set: []
},
}
});
return prisma.story.update({
where: { id },
data: {
title,
body,
cover_image: '',
excerpt,
is_published: was_published || is_published,
tags: {
connectOrCreate:
tags.map(tag => {
tag = tag.toLowerCase().trim();
return {
where: {
title: tag,
},
create: {
title: tag
}
}
})
},
body_image_ids: bodyImageIds,
...coverImageRel
}
})
.catch(error => {
logError(error)
throw new ApolloError("Unexpected error happened...")
})
}
} : {}
if (id) {
await prisma.story.update({
where: { id },
data: {
tags: {
set: []
},
}
});
return prisma.story.update({
where: { id },
return prisma.story.create({
data: {
title,
body,
cover_image: '',
excerpt,
is_published: was_published || is_published,
is_published,
tags: {
connectOrCreate:
tags.map(tag => {
@@ -540,42 +573,24 @@ const createStory = extendType({
}
})
},
user: {
connect: {
id: user.id,
}
},
body_image_ids: bodyImageIds,
...coverImageRel
}
}).catch(error => {
logError(error)
throw new ApolloError("Unexpected error happened...")
})
}
return await prisma.story.create({
data: {
title,
body,
cover_image: '',
excerpt,
is_published,
tags: {
connectOrCreate:
tags.map(tag => {
tag = tag.toLowerCase().trim();
return {
where: {
title: tag,
},
create: {
title: tag
}
}
})
},
user: {
connect: {
id: user.id,
}
},
body_image_ids: bodyImageIds,
...coverImageRel
}
})
} catch (error) {
logError(error)
throw new ApolloError("Unexpected error happened...")
}
}
})
},

View File

@@ -9,6 +9,7 @@ const jose = require('jose');
const { JWT_SECRET } = require('../../utils/consts');
const { generatePrivateKey, getPublicKey } = require('../../utils/nostr-tools');
const { getUserByPubKey } = require('../../auth/utils/helperFuncs');
const { logError } = require('../../utils/logger');
@@ -28,10 +29,18 @@ const loginHandler = async (req, res) => {
if (action === 'link' && user_token) {
try {
const { payload } = await jose.jwtVerify(user_token, Buffer.from(JWT_SECRET), {
algorithms: ['HS256'],
})
const user_id = payload.user_id;
let user_id;
try {
const { payload } = await jose.jwtVerify(user_token, Buffer.from(JWT_SECRET), {
algorithms: ['HS256'],
})
user_id = payload.user_id;
} catch (error) {
return res.status(400).json({ status: 'ERROR', reason: "Invalid user_token" })
}
const existingKeys = await prisma.userKey.findMany({ where: { user_id }, select: { key: true } });
if (existingKeys.length >= 3)
@@ -55,7 +64,8 @@ const loginHandler = async (req, res) => {
.json({ status: "OK" })
} catch (error) {
return res.status(400).json({ status: 'ERROR', reason: 'Invalid User Token' })
logError(error)
return res.status(500).json({ status: 'ERROR', reason: 'Unexpected error happened' })
}
}
@@ -65,8 +75,7 @@ const loginHandler = async (req, res) => {
const user = await getUserByPubKey(key)
if (user === null) {
// Check if user had a previous account using this wallet
// Check if user had a previous account using this wallet
const oldAccount = await prisma.user.findFirst({
where: {
pubKey: key
@@ -136,7 +145,8 @@ const loginHandler = async (req, res) => {
return res.status(200).json({ status: "OK" })
} catch (error) {
return res.status(400).json({ status: 'ERROR', reason: 'Unexpected error happened, please try again' })
logError(error)
return res.status(500).json({ status: 'ERROR', reason: 'Unexpected error happened, please try again' })
}
}

9
api/utils/logger.js Normal file
View File

@@ -0,0 +1,9 @@
function logError(error) {
console.log("Unexpected Error: ");
console.log(error);
}
module.exports = {
logError
}

View File

@@ -9,8 +9,39 @@ interface Props {
export default function PrizesSection({ prizes }: Props) {
return (
<div>
<h2 className='text-body1 font-bolder text-gray-900 mb-16'>Prizes</h2>
<div className={styles.grid}>
<h2 className='text-body1 font-bolder text-gray-900 mb-16'>{data.tracks.length > 0 ? "Prizes & Tracks" : "Prizes"}</h2>
<div className="flex flex-col gap-16">
{data.tracks.map((track, trackNumber) => <div key={track.id}
className="bg-gray-50 rounded-16 border-2 border-gray-100 p-16 md:p-40"
>
<div className="flex justify-between gap-24 flex-col md:flex-row">
<div className='flex flex-col items-start gap-8 max-w-[400px]'>
<img src={track.image} alt={`${track.title} track prize`} className='h-[64px]' />
<h3 className="text-body2 text-gray-900 font-bolder">{track.title}</h3>
<p className="text-body4 text-gray-500">{track.description}</p>
</div>
<div className={`text-right ${styles.prizes}`}>
{/* One Prize */}
{track.prizes.length === 1 &&
<div>
<h4 className='text-[32px]'>{track.prizes[0].title}</h4>
<p className='text-[118px]' data-attr={trackNumber + 1}>{track.prizes[0].amount}</p>
</div>
}
{/* Four Prizez */}
{track.prizes.length === 4 &&
<div className='flex justify-end flex-wrap gap-40'>
{track.prizes.map((prize, idx) => <div key={prize.id} className='first:w-full'>
<h4 className={`${idx === 0 ? "text-h2" : "text-body2"}`}>{prize.title}</h4>
<p className={`${idx === 0 ? "text-[48px]" : "text-[36px]"}`} data-attr={trackNumber + 1}>{prize.amount}</p>
</div>)}
</div>
}
</div>
</div>
</div>)}
</div>
{/* <div className={styles.grid}>
{prizes.map((prize, idx) => <div
key={idx}
className='bg-gray-50 rounded-16 py-24 px-32'>
@@ -20,7 +51,82 @@ export default function PrizesSection({ prizes }: Props) {
<p className="text-h1 text-green-500">{prize.amount}</p>
</div>
</div>)}
</div>
</div> */}
</div>
)
}
const data = {
prizes: [],
tracks: [
{
id: 1,
title: "Grand Champion",
description: "Our Grand Champion, a.k.a “The Legend of Lightning” will be the best in show, la créme de la créme. Every project entered in the tournament will be eligible for this award, no matter what track they choose.",
image: "https://s3-alpha-sig.figma.com/img/33fa/68dc/1015f7806d8706cbb29b057f85482755?Expires=1664755200&Signature=QdesbJJcLG84k-SudRv9ah-tVSf~zv4NZKU1EQM9cz-L7qZ1crx7awSVBFZdP~p4R7h1FsUqQfSNHsOPQOKTRiWOL~mpKLe6SAlKhdeqrm8RCNmnhNHpMOxJrCGAsJ7vQDkUKFw9VsJjufTjtEgLHN-EWH5L~RvNHKa06f6rRyiMeRl5HCu9JWT5Spjb0zK7IrU2gT7G~Dw0FTdbE35uxCbN9pU-XuPLbqmAIsPBR-gV4uuf21NBapFOLFDazi-tDzIJO--vH6C4RjuI-i3sl1WV75-SM0DW9MVNBvXiWfPrtGXbNd379xJXQoCBVxv4qzl3YkdoxFUG1-uwKTrVaA__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA",
prizes: [
{
id: 1,
title: "the legend",
amount: "1 BTC"
}
]
},
{
id: 2,
title: "Bitcoin Adoption Track",
description: "On-chain applications have been the bed rock of bitcoins explosive growth and adoption over the last decade. Slowly, steadily, and securely, bitcoins base layer always seeks to evolve and improve.",
image: "https://s3-alpha-sig.figma.com/img/cb90/77b4/5ea853a671d0cb1c64bde10dd8955d39?Expires=1664755200&Signature=aXtIhKJg58wRTQlJIGWxpfCN2hxJx8L0~8Hu5aH8LKUVAYrxSV5Tvvxevx9xDnf-RpjTVfB6D7RKuVQjfIiftB4Ym80oOlW9tNzYUo991cJhdYnqaGzJ6Ht2kF7NHmxbiY5RUMYj8bGf2AF1A2a7wuW~DaqHyLQ0s2sszwH2EAv31QTH1DAOO97pQzQ5asas7qGjARWh45QEfw6F8e~6iq3UWHXtIcJ0HMJO4q3ONhsMkuC6XQNfAmWTRwKb3tPZ79oehWgDeyOMGQkRS0uaal~6fNkheEN5DuRBH2dbXtqB6va0PJCTB1l8P558HXhKQjHXRLPPReIci72jPuTzdA__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA",
prizes: [
{
id: 2,
title: " 1st",
amount: "$5k"
},
{
id: 3,
title: " 2nd",
amount: "$2.5k"
},
{
id: 4,
title: " 3rd",
amount: "$1.5k"
},
{
id: 5,
title: " Design",
amount: "$1k"
},
]
},
{
id: 3,
title: "Building for Africa track",
description: "With ~1.4bn inhabitants, Africa is ripe for bitcoin adoption. In partnership with ABC 22, this track seeks to encourage makers to build solutions that are local to the African continent.",
image: "https://s3-alpha-sig.figma.com/img/c306/f172/7ce7befa9414372e6d0ede739be46de8?Expires=1664755200&Signature=BBfOTJzk7Si7zs9dOBhTdIhoKCvUDxAr6Do0wCZaIq9PD2Jcfxu3ANbiogzihC5O2Rwz3sKsajsRCd8eSs8HGrHrQh89SfNIl0~MYjMz12yWpsc1vC5M5hmXH~VQzCTOWsSki9BimcpCu0IOWfJFjY-p0rlo8UFhdDe56DiRUOSW0pAm5UxTstzOew6X015xA3qQWwUIea2JAtlsI5RqMQMRB-QlaKFlQvYHBU6YzLUNTuTn4MfOd-1oZXKtDArubYnSrJb2rJAXqccxgsXceDl8jq8HXKwkBR95-sG3UDZB7q7qb1Nk3HlsDtirGNlOjLx~vDKpOuyIk5ufAkdJmQ__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA",
prizes: [
{
id: 6,
title: " 1st",
amount: "$5k"
},
{
id: 7,
title: " 2nd",
amount: "$2.5k"
},
{
id: 8,
title: " 3rd",
amount: "$1.5k"
},
{
id: 9,
title: " Design",
amount: "$1k"
},
]
},
]
}

View File

@@ -2,6 +2,32 @@
@import url("https://fonts.googleapis.com/css2?family=Luckiest+Guy&display=swap");
.prizes {
font-family: "Luckiest Guy", cursive;
h4 {
color: white;
-webkit-text-stroke: 1px black;
}
@include gt-md {
h4 {
-webkit-text-stroke: 0.06em black;
}
}
p[data-attr="1"] {
color: #fb923c;
}
p[data-attr="2"] {
color: #4ade80;
}
p[data-attr="3"] {
color: #3b82f6;
}
}
.grid {
font-family: "Luckiest Guy", cursive;
display: grid;