Skip to content

Commit

Permalink
fix(general): fix timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
Giacomo Materozzi committed May 14, 2024
1 parent a941343 commit 3e2447c
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 82 deletions.
7 changes: 7 additions & 0 deletions app/api/projects/[projectId]/keywords/import-analyze/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ export async function POST(
keyword: {
in: body.keywords,
},
translations: {
every: {
projectLanguageId: {
equals: params.projectId,
},
},
},
},
})

Expand Down
175 changes: 125 additions & 50 deletions app/api/projects/[projectId]/keywords/import/route.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Prisma } from "@prisma/client"
import { getServerSession } from "next-auth/next"
import * as z from "zod"

Expand Down Expand Up @@ -50,67 +51,141 @@ export async function POST(
return ErrorResponse({ error: i18n.t("Language not found"), status: 404 })
}

const keywordsAlreadyExists = await db.keyword.findMany({
where: {
keyword: {
in: Object.keys(body.keywords),
},
projectId: params.projectId,
},
select: {
id: true,
keyword: true,
},
})
type keywordAlreadyExistsType = {
id: string
keyword: string
translations: {
projectLanguageId: string
}[]
}

const keywordsToUpdate = keywordsAlreadyExists.map((keyword) => ({
keyword: keyword.keyword,
id: keyword.id,
value: body.keywords[keyword.keyword],
}))
const keywordsToCreate = Object.keys(body.keywords).filter(
(keyword) =>
!keywordsToUpdate.map((keyword) => keyword.keyword).includes(keyword)
)

for (let i = 0; i < keywordsToUpdate.length; i++) {
const keywordToUpdate = keywordsToUpdate[i]
const result = await db.translation.updateMany({
const keywordsAlreadyExists: keywordAlreadyExistsType[] =
await db.keyword.findMany({
where: {
keywordId: keywordToUpdate.id,
projectLanguageId: projectLanguageId.id,
keyword: {
in: Object.keys(body.keywords),
},
projectId: params.projectId,
},
data: {
value: keywordToUpdate.value,
select: {
id: true,
keyword: true,
translations: {
select: {
projectLanguageId: true,
},
},
},
})

if (result.count === 0) {
await db.translation.create({
data: {
value: body.keywords[keywordToUpdate.keyword],
projectLanguageId: projectLanguageId.id,
keywordId: keywordToUpdate.id,
},
})
const translationExists = (keyword: keywordAlreadyExistsType) =>
keyword.translations.find(
(translation) => translation.projectLanguageId === projectLanguageId.id
)

const translationToUpdate = keywordsAlreadyExists
.filter(translationExists)
.map((keyword) => ({
keyword: keyword.keyword,
id: keyword.id,
value: body.keywords[keyword.keyword],
}))

const translationToCreate = keywordsAlreadyExists
.filter((key) => !translationExists(key))
.map((keyword) => ({
keyword: keyword.keyword,
id: keyword.id,
value: body.keywords[keyword.keyword],
}))

const keywordsToCreate = Object.keys(body.keywords).filter((keyword) => {
const translationToUpdateKeywords = translationToUpdate.map(
(keyword) => keyword.keyword
)
const translationToCreateKeywords = translationToCreate.map(
(keyword) => keyword.keyword
)
if (
keyword.length > 0 &&
!translationToUpdateKeywords.includes(keyword) &&
!translationToCreateKeywords.includes(keyword)
) {
return true
}
}
return false
})

for (let i = 0; i < keywordsToCreate.length; i++) {
const keywordToCreate = keywordsToCreate[i]
await db.keyword.create({
data: {
keyword: keywordToCreate,
projectId: params.projectId,
context: "",
translations: {
create: {
value: body.keywords[keywordToCreate],
projectLanguageId: projectLanguageId.id,
},
if (translationToUpdate.length) {
await db.translation.deleteMany({
where: {
keywordId: {
in: translationToUpdate.map((keyword) => keyword.id),
},
projectLanguageId: projectLanguageId.id,
},
})

await db.$queryRaw`
INSERT INTO "translations" ("id", "keywordId", "projectLanguageId", "value")
VALUES ${Prisma.join(
translationToUpdate.map(
(keyword) =>
Prisma.sql`(gen_random_uuid(), ${Prisma.join([
keyword.id,
projectLanguageId.id,
body.keywords[keyword.keyword],
])})`
)
)}`
}

if (translationToCreate.length) {
await db.$queryRaw`
INSERT INTO "translations" ("id", "keywordId", "projectLanguageId", "value")
VALUES ${Prisma.join(
translationToCreate.map(
(keyword) =>
Prisma.sql`(gen_random_uuid(), ${Prisma.join([
keyword.id,
projectLanguageId.id,
body.keywords[keyword.keyword],
])})`
)
)}`
}

if (keywordsToCreate.length) {
const keywordIds: { id: string }[] = await db.$queryRaw`
INSERT INTO "keywords" ("id", "keyword", "projectId", "context")
VALUES ${Prisma.join(
keywordsToCreate.map(
(keywordToCreate) =>
Prisma.sql`(gen_random_uuid(), ${Prisma.join([
keywordToCreate,
params.projectId,
"",
])})`
)
)}
RETURNING id`

if (keywordIds.length !== keywordsToCreate.length) {
return ErrorResponse({ error: i18n.t("Error creating keywords") })
}

await db.$queryRaw`
INSERT INTO "translations" ("id", "keywordId", "projectLanguageId", "value")
VALUES ${Prisma.join(
keywordsToCreate.map(
(keywordToCreate, index) =>
Prisma.sql`(gen_random_uuid(), ${Prisma.join([
keywordIds[index].id,
projectLanguageId.id,
body.keywords[keywordToCreate],
])})`
)
)}`
}

return SuccessResponse()
Expand Down
5 changes: 2 additions & 3 deletions components/app/project/dialogs/import-keywords.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,6 @@ const ImportKeywordsModal = (props: ImportKeywordsModalProps) => {
}

importKeywords(jsonData)
reset()
setOpen(false)
} catch (error) {
toast({
title: i18n.t("Something went wrong"),
Expand Down Expand Up @@ -318,7 +316,7 @@ const ImportKeywordsModal = (props: ImportKeywordsModalProps) => {
onClick={analyzeKeywords}
disabled={!textJSON || !languageSelected || !isJson(textJSON)}
>
{isPendingAnalyze ? (
{isPendingAnalyze || isPendingImportKeywords ? (
<Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
) : (
<Fragment />
Expand All @@ -333,6 +331,7 @@ const ImportKeywordsModal = (props: ImportKeywordsModalProps) => {
handleChangeTextJSON,
handleFile,
isPendingAnalyze,
isPendingImportKeywords,
languageSelected,
languages,
textJSON,
Expand Down
14 changes: 14 additions & 0 deletions hooks/api/project/keyword/use-edit-keyword.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import axios from "axios"
import { ApiResponseType } from "@/types/api"
import { handleApiError } from "@/lib/exceptions"

import { getLanguagesQueryKey } from "../language/use-get-languages"
import { getTranslationKey } from "./translation/use-get-all-translations"
import { getKeywordsQueryKey } from "./use-get-keywords"

const editKeyword = async (
Expand Down Expand Up @@ -48,9 +50,21 @@ export const useEditKeyword = ({
queryClient.cancelQueries({
queryKey: getKeywordsQueryKey(projectId),
})
queryClient.cancelQueries({
queryKey: getTranslationKey(projectId, keywordId),
})
queryClient.cancelQueries({
queryKey: getLanguagesQueryKey(projectId),
})
queryClient.refetchQueries({
queryKey: getKeywordsQueryKey(projectId),
})
queryClient.refetchQueries({
queryKey: getTranslationKey(projectId, keywordId),
})
queryClient.refetchQueries({
queryKey: getLanguagesQueryKey(projectId),
})
},
})
}
5 changes: 3 additions & 2 deletions lib/i18n/languages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@
"Edit word: {keyword}": "Edit word: {{keyword}}",
"Email": "Email",
"Email already exists": "Email already exists",
"This email is already in use": "This email is already in use",
"Email verified successfully": "Email verified successfully",
"Email verified successfully. Please relogin": "Email verified successfully. Please relogin",
"Enter the new email": "Enter the new email",
"Enter the old and the new password": "Enter the old and the new password",
"Enter your email below to create your account": "Enter your email below to create your account",
"Enter your email here, and we will send you a link where you can reset your password": "Enter your email here, and we will send you a link where you can reset your password",
"Enter your email to sign in to your account": "Enter your email to sign in to your account",
"Error creating keywords": "Error creating keywords",
"Error parsing JSON": "Error parsing JSON",
"Exit without saving": "Exit without saving",
"Export Translations": "Export Translations",
Expand Down Expand Up @@ -188,6 +188,7 @@
"This action cannot be undone": "This action cannot be undone",
"This context is <b>optional</b> and can be provided alongside the keyword, aiding the AI in its translation process.": "This context is <b>optional</b> and can be provided alongside the keyword, aiding the AI in its translation process.",
"This context is optional and can be provided alongside the keyword, aiding the AI in its translation process.": "This context is <b>optional</b> and can be provided alongside the keyword, aiding the AI in its translation process.",
"This email is already in use": "This email is already in use",
"This transition cound not be found. Please try again.": "This transition cound not be found. Please try again.",
"To achieve a well-done translation, we need to provide context to the AI.": "To achieve a well-done translation, we need to provide context to the AI.",
"To buy more AI tokens, a subscription is required": "To buy more AI tokens, a subscription is required",
Expand Down Expand Up @@ -248,4 +249,4 @@
"{MAX_PROJECTS_STARTER_URSER} project": "{{MAX_PROJECTS_STARTER_URSER}} project",
"{number} tokens AI translations one-time": "{{number}} tokens AI translations one-time",
"♥️": "♥️"
}
}
41 changes: 20 additions & 21 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,26 @@ const nextConfig = {
appDir: true,
serverComponentsExternalPackages: ["@prisma/client"],
},
async headers() {
return [
{
source: "/api/:path*", // matching all API routes
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Origin", value: "*" },
{
key: "Access-Control-Allow-Methods",
value: "GET,DELETE,PATCH,POST,PUT",
},
{
key: "Access-Control-Allow-Headers",
value:
"X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
},
],
},
]
},
}

export default withSentryConfig(
Expand Down Expand Up @@ -52,26 +72,5 @@ export default withSentryConfig(
// https://docs.sentry.io/product/crons/
// https://vercel.com/docs/cron-jobs
automaticVercelMonitors: true,

async headers() {
return [
{
source: "/api/:path*", // matching all API routes
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Origin", value: "*" },
{
key: "Access-Control-Allow-Methods",
value: "GET,DELETE,PATCH,POST,PUT",
},
{
key: "Access-Control-Allow-Headers",
value:
"X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
},
],
},
]
},
}
)
10 changes: 5 additions & 5 deletions prisma/migrations/20240419084810_add_keywords/migration.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ CREATE TABLE "project_language" (
);

-- CreateTable
CREATE TABLE "traslations" (
CREATE TABLE "translations" (
"id" TEXT NOT NULL,
"keywordId" TEXT NOT NULL,
"projectLanguageId" TEXT NOT NULL,
"value" TEXT NOT NULL,
"history" JSONB,

CONSTRAINT "traslations_pkey" PRIMARY KEY ("id")
CONSTRAINT "translations_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
Expand All @@ -47,7 +47,7 @@ CREATE UNIQUE INDEX "keywords_keyword_projectId_key" ON "keywords"("keyword", "p
CREATE UNIQUE INDEX "project_language_short_projectId_key" ON "project_language"("short", "projectId");

-- CreateIndex
CREATE UNIQUE INDEX "traslations_keywordId_projectLanguageId_key" ON "traslations"("keywordId", "projectLanguageId");
CREATE UNIQUE INDEX "translations_keywordId_projectLanguageId_key" ON "translations"("keywordId", "projectLanguageId");

-- AddForeignKey
ALTER TABLE "keywords" ADD CONSTRAINT "keywords_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
Expand All @@ -56,7 +56,7 @@ ALTER TABLE "keywords" ADD CONSTRAINT "keywords_projectId_fkey" FOREIGN KEY ("pr
ALTER TABLE "project_language" ADD CONSTRAINT "project_language_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "traslations" ADD CONSTRAINT "traslations_keywordId_fkey" FOREIGN KEY ("keywordId") REFERENCES "keywords"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "translations" ADD CONSTRAINT "translations_keywordId_fkey" FOREIGN KEY ("keywordId") REFERENCES "keywords"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "traslations" ADD CONSTRAINT "traslations_projectLanguageId_fkey" FOREIGN KEY ("projectLanguageId") REFERENCES "project_language"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "translations" ADD CONSTRAINT "translations_projectLanguageId_fkey" FOREIGN KEY ("projectLanguageId") REFERENCES "project_language"("id") ON DELETE CASCADE ON UPDATE CASCADE;
2 changes: 1 addition & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ model Translation {
history Json?
@@unique([keywordId, projectLanguageId])
@@map(name: "traslations")
@@map(name: "translations")
}

model AiTranslationsLog {
Expand Down
Loading

0 comments on commit 3e2447c

Please sign in to comment.