[questions][feat] add tags

pull/510/head
hpkoh 3 years ago
parent 32302e33a5
commit 59b1dc68f3

@ -0,0 +1,28 @@
-- CreateTable
CREATE TABLE "QuestionTags" (
"id" TEXT NOT NULL,
"tag" TEXT NOT NULL,
CONSTRAINT "QuestionTags_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "QuestionQuestionTagEntry" (
"id" TEXT NOT NULL,
"questionId" TEXT NOT NULL,
"tagId" TEXT NOT NULL,
CONSTRAINT "QuestionQuestionTagEntry_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "QuestionTags_tag_key" ON "QuestionTags"("tag");
-- CreateIndex
CREATE UNIQUE INDEX "QuestionQuestionTagEntry_questionId_tagId_key" ON "QuestionQuestionTagEntry"("questionId", "tagId");
-- AddForeignKey
ALTER TABLE "QuestionQuestionTagEntry" ADD CONSTRAINT "QuestionQuestionTagEntry_questionId_fkey" FOREIGN KEY ("questionId") REFERENCES "QuestionsQuestion"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "QuestionQuestionTagEntry" ADD CONSTRAINT "QuestionQuestionTagEntry_tagId_fkey" FOREIGN KEY ("tagId") REFERENCES "QuestionTags"("id") ON DELETE CASCADE ON UPDATE CASCADE;

@ -0,0 +1,25 @@
/*
Warnings:
- You are about to drop the `QuestionTags` table. If the table is not empty, all the data it contains will be lost.
*/
-- DropForeignKey
ALTER TABLE "QuestionQuestionTagEntry" DROP CONSTRAINT "QuestionQuestionTagEntry_tagId_fkey";
-- DropTable
DROP TABLE "QuestionTags";
-- CreateTable
CREATE TABLE "QuestionTag" (
"id" TEXT NOT NULL,
"tag" TEXT NOT NULL,
CONSTRAINT "QuestionTag_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "QuestionTag_tag_key" ON "QuestionTag"("tag");
-- AddForeignKey
ALTER TABLE "QuestionQuestionTagEntry" ADD CONSTRAINT "QuestionQuestionTagEntry_tagId_fkey" FOREIGN KEY ("tagId") REFERENCES "QuestionTag"("id") ON DELETE CASCADE ON UPDATE CASCADE;

@ -455,18 +455,36 @@ model QuestionsQuestion {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
encounters QuestionsQuestionEncounter[]
votes QuestionsQuestionVote[]
comments QuestionsQuestionComment[]
answers QuestionsAnswer[]
questionsListQuestionEntries QuestionsListQuestionEntry[]
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
encounters QuestionsQuestionEncounter[]
votes QuestionsQuestionVote[]
comments QuestionsQuestionComment[]
answers QuestionsAnswer[]
listQuestionEntries QuestionsListQuestionEntry[]
questionTagEntries QuestionQuestionTagEntry[]
@@index([lastSeenAt, id])
@@index([numEncounters, id])
@@index([upvotes, id])
}
model QuestionTag {
id String @id @default(cuid())
tag String @unique
questionTagEntries QuestionQuestionTagEntry[]
}
model QuestionQuestionTagEntry {
id String @id @default(cuid())
questionId String
tagId String
question QuestionsQuestion @relation(fields: [questionId], references: [id], onDelete: Cascade)
tag QuestionTag @relation(fields: [tagId], references: [id], onDelete: Cascade)
@@unique([questionId, tagId])
}
model QuestionsQuestionEncounter {
id String @id @default(cuid())
questionId String

@ -24,6 +24,7 @@ export const questionsQuestionRouter = createRouter()
sortType: z.nativeEnum(SortType),
startDate: z.date().optional(),
stateIds: z.string().array(),
tagIds: z.string().array(),
}),
async resolve({ ctx, input }) {
const { cursor } = input;
@ -82,6 +83,11 @@ export const questionsQuestionRouter = createRouter()
state: true,
},
},
questionTagEntries: {
select: {
tag: true,
},
},
user: {
select: {
name: true,
@ -99,6 +105,19 @@ export const questionsQuestionRouter = createRouter()
},
}
: {}),
...(input.tagIds.length > 0
? {
questionTagEntries: {
some : {
tag: {
id: {
in: input.tagIds,
},
},
}
},
}
: {}),
encounters: {
some: {
seenAt: {
@ -150,6 +169,7 @@ export const questionsQuestionRouter = createRouter()
: {}),
},
},
},
});
@ -197,6 +217,11 @@ export const questionsQuestionRouter = createRouter()
state: true,
},
},
questionTagEntries: {
select: {
tag: true,
},
},
user: {
select: {
name: true,
@ -262,6 +287,11 @@ export const questionsQuestionRouter = createRouter()
state: true,
},
},
questionTagEntries: {
select: {
tag: true,
},
},
user: {
select: {
name: true,
@ -298,6 +328,7 @@ export const questionsQuestionRouter = createRouter()
sortType: z.nativeEnum(SortType),
startDate: z.date().optional(),
stateIds: z.string().array(),
tagIds: z.string().array(),
}),
async resolve({ ctx, input }) {
const escapeChars = /[()|&:*!]/g;
@ -367,6 +398,11 @@ export const questionsQuestionRouter = createRouter()
state: true,
},
},
questionTagEntries: {
select: {
tag: true,
},
},
user: {
select: {
name: true,
@ -377,9 +413,6 @@ export const questionsQuestionRouter = createRouter()
orderBy: sortCondition,
take: input.limit + 1,
where: {
id: input.content !== "" ? {
in: relatedQuestionsIdArray,
} : undefined,
...(input.questionTypes.length > 0
? {
questionType: {
@ -387,6 +420,19 @@ export const questionsQuestionRouter = createRouter()
},
}
: {}),
...(input.tagIds.length > 0
? {
questionTagEntries: {
some : {
tag: {
id: {
in: input.tagIds,
},
},
}
},
}
: {}),
encounters: {
some: {
seenAt: {
@ -438,6 +484,7 @@ export const questionsQuestionRouter = createRouter()
: {}),
},
},
},
});

@ -0,0 +1,81 @@
import { z } from 'zod';
import { createProtectedRouter } from '../context';
export const questionsTagUserRouter = createProtectedRouter()
.mutation('create', {
input: z.object({
tag: z.string(),
}),
async resolve({ ctx, input }) {
return await ctx.prisma.questionTag.upsert({
where: {
tag : input.tag,
},
update: {},
create : {
tag : input.tag,
}
});
},
})
.mutation('addTagToQuestion', {
input: z.object({
questionId: z.string(),
tagId: z.string(),
}),
async resolve({ ctx, input }) {
return await ctx.prisma.questionQuestionTagEntry.create({
data: {
question:{
connect: {
id: input.questionId,
},
},
tag:{
connect: {
id: input.tagId,
},
},
},
});
},
})
.mutation('removeTagFromQuestion', {
input: z.object({
id: z.string(),
}),
async resolve({ ctx, input }) {
return await ctx.prisma.questionQuestionTagEntry.delete({
where: {
id: input.id,
},
});
}
})
.mutation('combineTags', {
input: z.object({
tagToCombineId: z.string(),
tagToCombineToId: z.string(),
}),
async resolve({ ctx, input }) {
return await ctx.prisma.$transaction(async (tx) => {
const questionTagsUpdated = await tx.questionQuestionTagEntry.updateMany({
where: {
tagId: input.tagToCombineId,
},
data: {
tagId: input.tagToCombineId,
},
});
tx.questionTag.delete({
where: {
id: input.tagToCombineId,
},
});
return questionTagsUpdated;
});
}
});

@ -5,6 +5,7 @@ export type Question = {
content: string;
id: string;
numAnswers: number;
tags: Array<QuestionTag>;
numComments: number;
numVotes: number;
receivedCount: number;

@ -4,6 +4,7 @@ import type {
Country,
QuestionsQuestion,
QuestionsQuestionVote,
QuestionTag,
State,
} from '@prisma/client';
import { Vote } from '@prisma/client';
@ -14,6 +15,8 @@ import type {
Question,
} from '~/types/questions';
type QuestionTagEntry = { tag: QuestionTag; }
type AggregatableEncounters = Array<{
city: City | null;
company: Company | null;
@ -28,6 +31,7 @@ type QuestionWithAggregatableData = QuestionsQuestion & {
answers: number;
comments: number;
};
questionTagEntries: Array<QuestionTagEntry>;
encounters: AggregatableEncounters;
user: {
name: string | null;
@ -66,6 +70,7 @@ export function createQuestionWithAggregateData(
numVotes: votes,
receivedCount: data.encounters.length,
seenAt: data.encounters[0].seenAt,
tags: data.tags,
type: data.questionType,
updatedAt: data.updatedAt,
user: data.user?.name ?? '',

Loading…
Cancel
Save