db portion of mentions
This commit is contained in:
parent
534e772849
commit
3370675d61
@ -61,9 +61,12 @@ export default {
|
|||||||
},
|
},
|
||||||
moreFlatComments: async (parent, { cursor, userId }, { me, models }) => {
|
moreFlatComments: async (parent, { cursor, userId }, { me, models }) => {
|
||||||
const decodedCursor = decodeCursor(cursor)
|
const decodedCursor = decodeCursor(cursor)
|
||||||
let comments
|
|
||||||
if (userId) {
|
if (!userId) {
|
||||||
comments = await models.$queryRaw(`
|
throw new UserInputError('must supply userId', { argumentName: 'userId' })
|
||||||
|
}
|
||||||
|
|
||||||
|
const comments = await models.$queryRaw(`
|
||||||
${SELECT}
|
${SELECT}
|
||||||
FROM "Item"
|
FROM "Item"
|
||||||
WHERE "userId" = $1 AND "parentId" IS NOT NULL
|
WHERE "userId" = $1 AND "parentId" IS NOT NULL
|
||||||
@ -71,20 +74,7 @@ export default {
|
|||||||
ORDER BY created_at DESC
|
ORDER BY created_at DESC
|
||||||
OFFSET $3
|
OFFSET $3
|
||||||
LIMIT ${LIMIT}`, Number(userId), decodedCursor.time, decodedCursor.offset)
|
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)
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
cursor: comments.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
cursor: comments.length === LIMIT ? nextCursorEncoded(decodedCursor) : null,
|
||||||
comments
|
comments
|
||||||
@ -144,10 +134,7 @@ export default {
|
|||||||
throw new UserInputError('item can no longer be editted')
|
throw new UserInputError('item can no longer be editted')
|
||||||
}
|
}
|
||||||
|
|
||||||
return await models.item.update({
|
return await updateItem(parent, { id, data: { title, url: ensureProtocol(url) } }, { me, models })
|
||||||
where: { id: Number(id) },
|
|
||||||
data: { title, url: ensureProtocol(url) }
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
createDiscussion: async (parent, { title, text }, { me, models }) => {
|
createDiscussion: async (parent, { title, text }, { me, models }) => {
|
||||||
if (!title) {
|
if (!title) {
|
||||||
@ -175,10 +162,7 @@ export default {
|
|||||||
throw new UserInputError('item can no longer be editted')
|
throw new UserInputError('item can no longer be editted')
|
||||||
}
|
}
|
||||||
|
|
||||||
return await models.item.update({
|
return await updateItem(parent, { id, data: { title, text } }, { me, models })
|
||||||
where: { id: Number(id) },
|
|
||||||
data: { title, text }
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
createComment: async (parent, { text, parentId }, { me, models }) => {
|
createComment: async (parent, { text, parentId }, { me, models }) => {
|
||||||
if (!text) {
|
if (!text) {
|
||||||
@ -210,10 +194,7 @@ export default {
|
|||||||
throw new UserInputError('comment can no longer be editted')
|
throw new UserInputError('comment can no longer be editted')
|
||||||
}
|
}
|
||||||
|
|
||||||
return await models.item.update({
|
return await updateItem(parent, { id, data: { text } }, { me, models })
|
||||||
where: { id: Number(id) },
|
|
||||||
data: { text }
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
vote: async (parent, { id, sats = 1 }, { me, models }) => {
|
vote: async (parent, { id, sats = 1 }, { me, models }) => {
|
||||||
// need to make sure we are logged in
|
// 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 }) => {
|
const createItem = async (parent, { title, url, text, parentId }, { me, models }) => {
|
||||||
if (!me) {
|
if (!me) {
|
||||||
throw new AuthenticationError('you must be logged in')
|
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(
|
const [item] = await serialize(models, models.$queryRaw(
|
||||||
`${SELECT} FROM create_item($1, $2, $3, $4, $5) AS "Item"`,
|
`${SELECT} FROM create_item($1, $2, $3, $4, $5) AS "Item"`,
|
||||||
title, url, text, Number(parentId), me.name))
|
title, url, text, Number(parentId), me.name))
|
||||||
|
|
||||||
|
await createMentions(item, models)
|
||||||
|
|
||||||
item.comments = []
|
item.comments = []
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
22
prisma/migrations/20210818204542_mentions/migration.sql
Normal file
22
prisma/migrations/20210818204542_mentions/migration.sql
Normal file
@ -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")
|
emailVerified DateTime? @map(name: "email_verified")
|
||||||
image String?
|
image String?
|
||||||
items Item[]
|
items Item[]
|
||||||
|
mentions Mention[]
|
||||||
messages Message[]
|
messages Message[]
|
||||||
votes Vote[]
|
votes Vote[]
|
||||||
invoices Invoice[]
|
invoices Invoice[]
|
||||||
@ -60,6 +61,7 @@ model Item {
|
|||||||
parentId Int?
|
parentId Int?
|
||||||
children Item[] @relation("ParentChildren")
|
children Item[] @relation("ParentChildren")
|
||||||
votes Vote[]
|
votes Vote[]
|
||||||
|
mentions Mention[]
|
||||||
path Unsupported("LTREE")?
|
path Unsupported("LTREE")?
|
||||||
|
|
||||||
@@index([userId])
|
@@index([userId])
|
||||||
@ -81,6 +83,20 @@ model Vote {
|
|||||||
@@index([userId])
|
@@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 {
|
model Invoice {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
createdAt DateTime @default(now()) @map(name: "created_at")
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user