Skip to content

Commit

Permalink
fix(general): fixed settings and imports
Browse files Browse the repository at this point in the history
  • Loading branch information
Giacomo Materozzi committed Apr 29, 2024
1 parent 16ef3e6 commit 8ad3707
Show file tree
Hide file tree
Showing 14 changed files with 675 additions and 284 deletions.
51 changes: 51 additions & 0 deletions app/api/projects/[projectId]/keywords/import-analyze/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { getServerSession } from "next-auth/next"
import * as z from "zod"

import { authOptions } from "@/lib/auth"
import { db } from "@/lib/db"
import { handleCatchApi } from "@/lib/exceptions"
import i18n from "@/lib/i18n"
import { ErrorResponse } from "@/lib/response"

import {
routeContextSchemaProject,
verifyCurrentUserHasAccessToProject,
} from "../../route"

const keywordImportSchema = z.object({
keywords: z.array(z.string()),
})

export async function POST(
req: Request,
context: z.infer<typeof routeContextSchemaProject>
) {
try {
const { params } = routeContextSchemaProject.parse(context)

if (!(await verifyCurrentUserHasAccessToProject(params.projectId))) {
return ErrorResponse({ error: i18n.t("Wrong user"), status: 403 })
}

const session = await getServerSession(authOptions)

if (!session) {
return new Response("Unauthorized", { status: 403 })
}

const json = await req.json()
const body = keywordImportSchema.parse(json)

const keywordsAlreadyExists = await db.keyword.findMany({
where: {
keyword: {
in: body.keywords,
},
},
})

return new Response(JSON.stringify(keywordsAlreadyExists))
} catch (error) {
return handleCatchApi(error)
}
}
120 changes: 120 additions & 0 deletions app/api/projects/[projectId]/keywords/import/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { getServerSession } from "next-auth/next"
import * as z from "zod"

import { authOptions } from "@/lib/auth"
import { db } from "@/lib/db"
import { handleCatchApi } from "@/lib/exceptions"
import i18n from "@/lib/i18n"
import { ErrorResponse, SuccessResponse } from "@/lib/response"

import {
routeContextSchemaProject,
verifyCurrentUserHasAccessToProject,
} from "../../route"

const keywordImportSchema = z.object({
keywords: z.record(z.string()),
languageId: z.string(),
})

export async function POST(
req: Request,
context: z.infer<typeof routeContextSchemaProject>
) {
try {
const { params } = routeContextSchemaProject.parse(context)

if (!(await verifyCurrentUserHasAccessToProject(params.projectId))) {
return ErrorResponse({ error: i18n.t("Wrong user"), status: 403 })
}

const session = await getServerSession(authOptions)

if (!session) {
return new Response("Unauthorized", { status: 403 })
}

const json = await req.json()
const body = keywordImportSchema.parse(json)

const projectLanguageId = await db.projectLanguage.findUnique({
where: {
id: body.languageId,
},
select: {
id: true,
},
})

if (!projectLanguageId) {
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,
},
})

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({
where: {
keywordId: keywordToUpdate.id,
projectLanguageId: projectLanguageId.id,
},
data: {
value: keywordToUpdate.value,
},
})

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

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,
},
},
},
})
}

return SuccessResponse()
} catch (error) {
return handleCatchApi(error)
}
}
5 changes: 3 additions & 2 deletions app/api/projects/[projectId]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ export async function GET(
return new Response("Unauthorized", { status: 403 })
}

const keyword = await db.keyword.findUnique({
const project = await db.project.findUnique({
where: {
id: params.projectId,
},
})
return new Response(JSON.stringify(keyword))

return new Response(JSON.stringify(project))
} catch (error) {
return handleCatchApi(error)
}
Expand Down
89 changes: 56 additions & 33 deletions components/app/project/dialogs/import-keywords.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { ChangeEvent, useCallback, useEffect, useMemo, useState } from "react"

import i18n from "@/lib/i18n"
import { cn, isJson } from "@/lib/utils"
import { useAnalyzeKeywordToImports } from "@/hooks/api/project/keyword/use-import-analyze-keywords"
import { useKeywordsImports } from "@/hooks/api/project/keyword/use-import-keywords"
import { Button, buttonVariants } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import {
Expand All @@ -28,19 +30,66 @@ export type KeywordsToOverwrite = {
}

type ImportKeywordsModalProps = {
projectId: string
keywords: KeywordData[]
languages: LanguageData[]
importKeys: (keywords: ImportKeywords, languageRef: string) => void
}

const ImportKeywordsModal = (props: ImportKeywordsModalProps) => {
const { keywords, languages, importKeys } = props
const { keywords, languages, projectId } = props

const [textJSON, setTextJSON] = useState("")
const [languageSelected, selectLanguage] = useState<LanguageData | undefined>(
undefined
)

const { mutate: importKeywords } = useKeywordsImports({
projectId,
languageId: languageSelected?.id,
onSuccess: () => {
reset()
setOpen(false)
},
})
const { mutate: analyzeKeywordsApi } = useAnalyzeKeywordToImports({
projectId,
onSuccess: (keywordsAlreadyExists) => {
if (!languageSelected) {
return
}
try {
const jsonData = JSON.parse(textJSON)

if (keywordsAlreadyExists.length) {
setKeywordsToOverwrite(
keywordsAlreadyExists.reduce(
(acc, keyword): KeywordsToOverwrite => ({
...acc,
[keyword.keyword]: {
new: jsonData[keyword.keyword],
old: keywords[keyword.keyword],
selected: false,
},
}),
{}
)
)
return
}

importKeywords(jsonData)
reset()
setOpen(false)
} catch (error) {
toast({
title: i18n.t("Something went wrong"),
description: i18n.t("Error parsing JSON"),
variant: "destructive",
})
}
},
})

const [open, setOpen] = useState(false)

const [keywordsToOverwrite, setKeywordsToOverwrite] =
Expand Down Expand Up @@ -148,46 +197,22 @@ const ImportKeywordsModal = (props: ImportKeywordsModalProps) => {
[keywordsToOverwrite]
)

const analyzeKeywords = useCallback(() => {
const analyzeKeywords = useCallback(async () => {
if (!languageSelected) {
return
}

try {
const jsonData = JSON.parse(textJSON)

const keywordsAlreadyExists = keywords.filter(
(keyword) => jsonData[keyword.keyword] !== undefined
)

if (keywordsAlreadyExists.length) {
setKeywordsToOverwrite(
keywordsAlreadyExists.reduce(
(acc, keyword): KeywordsToOverwrite => ({
...acc,
[keyword.keyword]: {
new: jsonData[keyword.keyword],
old: keywords[keyword.keyword],
selected: false,
},
}),
{}
)
)
return
}

importKeys(jsonData, languageSelected.short)
reset()
setOpen(false)
analyzeKeywordsApi(Object.keys(jsonData))
} catch (error) {
toast({
title: i18n.t("Something went wrong"),
description: i18n.t("Error parsing JSON"),
variant: "destructive",
})
}
}, [importKeys, keywords, languageSelected, reset, textJSON])
}, [analyzeKeywordsApi, languageSelected, textJSON])

const overwrtieKeywords = useCallback(() => {
if (!languageSelected) {
Expand All @@ -210,17 +235,15 @@ const ImportKeywordsModal = (props: ImportKeywordsModalProps) => {
{}
)

importKeys(jsonToSave, languageSelected.short)
reset()
setOpen(false)
importKeywords(jsonToSave)
} catch (error) {
toast({
title: i18n.t("Something went wrong"),
description: i18n.t("Error parsing JSON"),
variant: "destructive",
})
}
}, [importKeys, keywordsToOverwrite, languageSelected, reset, textJSON])
}, [importKeywords, keywordsToOverwrite, languageSelected, textJSON])

const InputKeywordsView = useMemo(() => {
return (
Expand Down
4 changes: 1 addition & 3 deletions components/app/project/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,9 @@ export function Editor(props: EditorProps) {
download={download}
/>
<ImportKeywordsModal
projectId={project.id}
keywords={project.keywords}
languages={project.languages}
importKeys={() => {
// TODO
}}
/>
<button
onClick={() => openProjectSettings(true)}
Expand Down
Loading

0 comments on commit 8ad3707

Please sign in to comment.