db portion of mentions
This commit is contained in:
parent
534e772849
commit
3370675d61
|
@ -61,30 +61,20 @@ export default {
|
|||
},
|
||||
moreFlatComments: async (parent, { cursor, userId }, { me, models }) => {
|
||||
const decodedCursor = decodeCursor(cursor)
|
||||
let comments
|
||||
if (userId) {
|
||||
comments = await models.$queryRaw(`
|
||||
${SELECT}
|
||||
FROM "Item"
|
||||
WHERE "userId" = $1 AND "parentId" IS NOT NULL
|
||||
AND created_at <= $2
|
||||
ORDER BY created_at DESC
|
||||
OFFSET $3
|
||||
LIMIT ${LIMIT}`, Number(userId), decodedCursor.time, decodedCursor.offset)
|
||||
} else {
|
||||
// notifications ... god such spagetti
|
||||
if (!me) {
|
||||
throw new AuthenticationError('you must be logged in')
|
||||
}
|
||||
comments = await models.$queryRaw(`
|
||||
${SELECT}
|
||||
From "Item"
|
||||
JOIN "Item" p ON "Item"."parentId" = p.id AND p."userId" = $1
|
||||
AND "Item"."userId" <> $1 AND "Item".created_at <= $2
|
||||
ORDER BY "Item".created_at DESC
|
||||
OFFSET $3
|
||||
LIMIT ${LIMIT}`, me.id, decodedCursor.time, decodedCursor.offset)
|
||||
|
||||
if (!userId) {
|
||||
throw new UserInputError('must supply userId', { argumentName: 'userId' })
|
||||
}
|
||||
|
||||
const comments = await models.$queryRaw(`
|
||||
${SELECT}
|
||||
FROM "Item"
|
||||
WHERE "userId" = $1 AND "parentId" IS NOT NULL
|
||||
AND created_at <= $2
|
||||
ORDER BY created_at DESC
|
||||
OFFSET $3
|
||||
LIMIT ${LIMIT}`, Number(userId), decodedCursor.time, decodedCursor.offset)
|
||||
|
||||
return {
|
||||
cursor: comments.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
||||
comments
|
||||
|
@ -144,10 +134,7 @@ export default {
|
|||
throw new UserInputError('item can no longer be editted')
|
||||
}
|
||||
|
||||
return await models.item.update({
|
||||
where: { id: Number(id) },
|
||||
data: { title, url: ensureProtocol(url) }
|
||||
})
|
||||
return await updateItem(parent, { id, data: { title, url: ensureProtocol(url) } }, { me, models })
|
||||
},
|
||||
createDiscussion: async (parent, { title, text }, { me, models }) => {
|
||||
if (!title) {
|
||||
|
@ -175,10 +162,7 @@ export default {
|
|||
throw new UserInputError('item can no longer be editted')
|
||||
}
|
||||
|
||||
return await models.item.update({
|
||||
where: { id: Number(id) },
|
||||
data: { title, text }
|
||||
})
|
||||
return await updateItem(parent, { id, data: { title, text } }, { me, models })
|
||||
},
|
||||
createComment: async (parent, { text, parentId }, { me, models }) => {
|
||||
if (!text) {
|
||||
|
@ -210,10 +194,7 @@ export default {
|
|||
throw new UserInputError('comment can no longer be editted')
|
||||
}
|
||||
|
||||
return await models.item.update({
|
||||
where: { id: Number(id) },
|
||||
data: { text }
|
||||
})
|
||||
return await updateItem(parent, { id, data: { text } }, { me, models })
|
||||
},
|
||||
vote: async (parent, { id, sats = 1 }, { me, models }) => {
|
||||
// need to make sure we are logged in
|
||||
|
@ -302,6 +283,56 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
const namePattern = /\B@[\w_]+/gi
|
||||
|
||||
const createMentions = async (item, models) => {
|
||||
// if we miss a mention, in the rare circumstance there's some kind of
|
||||
// failure, it's not a big deal so we don't do it transactionally
|
||||
// ideally, we probably would
|
||||
if (!item.text) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const mentions = item.text.match(namePattern).map(m => m.slice(1))
|
||||
if (mentions.length > 0) {
|
||||
const users = await models.user.findMany({
|
||||
where: {
|
||||
name: { in: mentions }
|
||||
}
|
||||
})
|
||||
|
||||
users.forEach(async user => {
|
||||
const data = {
|
||||
itemId: item.id,
|
||||
userId: user.id
|
||||
}
|
||||
|
||||
await models.mention.upsert({
|
||||
where: {
|
||||
itemId_userId: data
|
||||
},
|
||||
update: data,
|
||||
create: data
|
||||
})
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('mention failure', e)
|
||||
}
|
||||
}
|
||||
|
||||
const updateItem = async (parent, { id, data }, { me, models }) => {
|
||||
const item = await models.item.update({
|
||||
where: { id: Number(id) },
|
||||
data
|
||||
})
|
||||
|
||||
await createMentions(item, models)
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
const createItem = async (parent, { title, url, text, parentId }, { me, models }) => {
|
||||
if (!me) {
|
||||
throw new AuthenticationError('you must be logged in')
|
||||
|
@ -310,6 +341,9 @@ const createItem = async (parent, { title, url, text, parentId }, { me, models }
|
|||
const [item] = await serialize(models, models.$queryRaw(
|
||||
`${SELECT} FROM create_item($1, $2, $3, $4, $5) AS "Item"`,
|
||||
title, url, text, Number(parentId), me.name))
|
||||
|
||||
await createMentions(item, models)
|
||||
|
||||
item.comments = []
|
||||
return item
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
-- CreateTable
|
||||
CREATE TABLE "Mention" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||
"itemId" INTEGER NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Mention.itemId_index" ON "Mention"("itemId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Mention.userId_index" ON "Mention"("userId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Mention" ADD FOREIGN KEY ("itemId") REFERENCES "Item"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Mention" ADD FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- A unique constraint covering the columns `[itemId,userId]` on the table `Mention` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Mention.itemId_userId_unique" ON "Mention"("itemId", "userId");
|
|
@ -19,6 +19,7 @@ model User {
|
|||
emailVerified DateTime? @map(name: "email_verified")
|
||||
image String?
|
||||
items Item[]
|
||||
mentions Mention[]
|
||||
messages Message[]
|
||||
votes Vote[]
|
||||
invoices Invoice[]
|
||||
|
@ -60,6 +61,7 @@ model Item {
|
|||
parentId Int?
|
||||
children Item[] @relation("ParentChildren")
|
||||
votes Vote[]
|
||||
mentions Mention[]
|
||||
path Unsupported("LTREE")?
|
||||
|
||||
@@index([userId])
|
||||
|
@ -81,6 +83,20 @@ model Vote {
|
|||
@@index([userId])
|
||||
}
|
||||
|
||||
model Mention {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now()) @map(name: "created_at")
|
||||
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
||||
item Item @relation(fields: [itemId], references: [id])
|
||||
itemId Int
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
|
||||
@@unique([itemId, userId])
|
||||
@@index([itemId])
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
model Invoice {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now()) @map(name: "created_at")
|
||||
|
|
Loading…
Reference in New Issue