chore: removed environmentId from language services (#3070)

This commit is contained in:
Dhruwang Jariwala
2024-09-02 18:27:55 +05:30
committed by GitHub
parent 3e79ec9a61
commit 14e0d57091
6 changed files with 44 additions and 48 deletions

View File

@@ -41,7 +41,7 @@ const Page = async ({ params }: { params: { environmentId: string } }) => {
<SettingsCard
title="Multi-language surveys"
description="Add languages to create multi-language surveys.">
<EditLanguage product={product} environmentId={params.environmentId} />
<EditLanguage product={product} />
</SettingsCard>
</PageContentWrapper>
);

View File

@@ -214,7 +214,7 @@ export const createSurvey = async (page: Page, params: CreateSurveyParams) => {
.filter({ hasText: new RegExp(`^${addQuestion}$`) })
.nth(1)
.click();
await page.getByRole("button", { name: "Call-to-Action" }).click();
await page.getByRole("button", { name: "Statement (Call to Action)" }).click();
await page.getByPlaceholder("Your question here. Recall").fill(params.ctaQuestion.question);
await page.getByPlaceholder("Finish").fill(params.ctaQuestion.buttonLabel);

View File

@@ -20,7 +20,6 @@ import { LanguageRow } from "./language-row";
interface EditLanguageProps {
product: TProduct;
environmentId: string;
}
const checkIfDuplicateExists = (arr: string[]) => {
@@ -67,7 +66,7 @@ const validateLanguages = (languages: TLanguage[]) => {
return true;
};
export function EditLanguage({ product, environmentId }: EditLanguageProps) {
export function EditLanguage({ product }: EditLanguageProps) {
const [languages, setLanguages] = useState<TLanguage[]>(product.languages);
const [isEditing, setIsEditing] = useState(false);
const [confirmationModal, setConfirmationModal] = useState({
@@ -123,7 +122,7 @@ export function EditLanguage({ product, environmentId }: EditLanguageProps) {
const performLanguageDeletion = async (languageId: string) => {
try {
await deleteLanguageAction({ environmentId, languageId });
await deleteLanguageAction({ languageId, productId: product.id });
setLanguages((prev) => prev.filter((lang) => lang.id !== languageId));
toast.success("Language deleted successfully.");
// Close the modal after deletion
@@ -145,11 +144,11 @@ export function EditLanguage({ product, environmentId }: EditLanguageProps) {
languages.map((lang) => {
return lang.id === "new"
? createLanguageAction({
environmentId,
productId: product.id,
languageInput: { code: lang.code, alias: lang.alias },
})
: updateLanguageAction({
environmentId,
productId: product.id,
languageId: lang.id,
languageInput: { code: lang.code, alias: lang.alias },
});

View File

@@ -3,7 +3,6 @@
import { z } from "zod";
import { authenticatedActionClient } from "@formbricks/lib/actionClient";
import { checkAuthorization } from "@formbricks/lib/actionClient/utils";
import { getEnvironment } from "@formbricks/lib/environment/service";
import {
createLanguage,
deleteLanguage,
@@ -15,35 +14,30 @@ import {
getOrganizationIdFromProductId,
} from "@formbricks/lib/organization/utils";
import { ZId } from "@formbricks/types/common";
import { ResourceNotFoundError } from "@formbricks/types/errors";
import { ZLanguageInput } from "@formbricks/types/product";
const ZCreateLanguageAction = z.object({
environmentId: ZId,
productId: ZId,
languageInput: ZLanguageInput,
});
export const createLanguageAction = authenticatedActionClient
.schema(ZCreateLanguageAction)
.action(async ({ ctx, parsedInput }) => {
const environment = await getEnvironment(parsedInput.environmentId);
if (!environment) {
throw new ResourceNotFoundError("Environment", parsedInput.environmentId);
}
await checkAuthorization({
data: parsedInput.languageInput,
schema: ZLanguageInput,
userId: ctx.user.id,
organizationId: await getOrganizationIdFromProductId(environment.productId),
organizationId: await getOrganizationIdFromProductId(parsedInput.productId),
rules: ["language", "create"],
});
return await createLanguage(environment.productId, parsedInput.environmentId, parsedInput.languageInput);
return await createLanguage(parsedInput.productId, parsedInput.languageInput);
});
const ZDeleteLanguageAction = z.object({
environmentId: ZId,
languageId: ZId,
productId: ZId,
});
export const deleteLanguageAction = authenticatedActionClient
@@ -55,7 +49,7 @@ export const deleteLanguageAction = authenticatedActionClient
rules: ["language", "delete"],
});
return await deleteLanguage(parsedInput.environmentId, parsedInput.languageId);
return await deleteLanguage(parsedInput.languageId, parsedInput.productId);
});
const ZGetSurveysUsingGivenLanguageAction = z.object({
@@ -75,7 +69,7 @@ export const getSurveysUsingGivenLanguageAction = authenticatedActionClient
});
const ZUpdateLanguageAction = z.object({
environmentId: ZId,
productId: ZId,
languageId: ZId,
languageInput: ZLanguageInput,
});
@@ -91,5 +85,5 @@ export const updateLanguageAction = authenticatedActionClient
rules: ["language", "update"],
});
return await updateLanguage(parsedInput.environmentId, parsedInput.languageId, parsedInput.languageInput);
return await updateLanguage(parsedInput.productId, parsedInput.languageId, parsedInput.languageInput);
});

View File

@@ -11,6 +11,7 @@ import {
ZLanguageUpdate,
} from "@formbricks/types/product";
import { productCache } from "../product/cache";
import { getProduct } from "../product/service";
import { surveyCache } from "../survey/cache";
import { validateInputs } from "../utils/validate";
@@ -48,11 +49,12 @@ export const getLanguage = async (languageId: string): Promise<TLanguage & { pro
export const createLanguage = async (
productId: string,
environmentId: string,
languageInput: TLanguageInput
): Promise<TLanguage> => {
try {
validateInputs([productId, ZId], [environmentId, ZId], [languageInput, ZLanguageInput]);
validateInputs([productId, ZId], [languageInput, ZLanguageInput]);
const product = await getProduct(productId);
if (!product) throw new ResourceNotFoundError("Product not found", productId);
if (!languageInput.code) {
throw new ValidationError("Language code is required");
}
@@ -67,9 +69,10 @@ export const createLanguage = async (
select: languageSelect,
});
productCache.revalidate({
id: productId,
environmentId,
product.environments.forEach((environment) => {
productCache.revalidate({
environmentId: environment.id,
});
});
return language;
@@ -110,25 +113,20 @@ export const getSurveysUsingGivenLanguage = reactCache(async (languageId: string
}
});
export const deleteLanguage = async (environmentId: string, languageId: string): Promise<TLanguage> => {
export const deleteLanguage = async (languageId: string, productId: string): Promise<TLanguage> => {
try {
validateInputs([languageId, ZId]);
validateInputs([languageId, ZId], [productId, ZId]);
const product = await getProduct(productId);
if (!product) throw new ResourceNotFoundError("Product not found", productId);
const prismaLanguage = await prisma.language.delete({
where: { id: languageId },
select: { ...languageSelect, surveyLanguages: { select: { surveyId: true } } },
});
productCache.revalidate({
id: prismaLanguage.productId,
environmentId,
});
// revalidate cache of all connected surveys
prismaLanguage.surveyLanguages.forEach((surveyLanguage) => {
surveyCache.revalidate({
id: surveyLanguage.surveyId,
environmentId,
product.environments.forEach((environment) => {
productCache.revalidate({
id: prismaLanguage.productId,
environmentId: environment.id,
});
});
@@ -146,29 +144,34 @@ export const deleteLanguage = async (environmentId: string, languageId: string):
};
export const updateLanguage = async (
environmentId: string,
productId: string,
languageId: string,
languageInput: TLanguageUpdate
): Promise<TLanguage> => {
try {
validateInputs([languageId, ZId], [languageInput, ZLanguageUpdate]);
validateInputs([languageId, ZId], [languageInput, ZLanguageUpdate], [productId, ZId]);
const product = await getProduct(productId);
if (!product) throw new ResourceNotFoundError("Product not found", productId);
const prismaLanguage = await prisma.language.update({
where: { id: languageId },
data: { ...languageInput, updatedAt: new Date() },
select: { ...languageSelect, surveyLanguages: { select: { surveyId: true } } },
});
productCache.revalidate({
id: prismaLanguage.productId,
environmentId,
product.environments.forEach((environment) => {
productCache.revalidate({
id: prismaLanguage.productId,
environmentId: environment.id,
});
surveyCache.revalidate({
environmentId: environment.id,
});
});
// revalidate cache of all connected surveys
prismaLanguage.surveyLanguages.forEach((surveyLanguage) => {
surveyCache.revalidate({
id: surveyLanguage.surveyId,
environmentId,
});
});

View File

@@ -99,7 +99,7 @@ describe("Tests for deleteLanguage", () => {
it("Deletes a Language", async () => {
prismaMock.language.delete.mockResolvedValue(mockLanguage);
const language = await deleteLanguage(mockEnvironmentId, mockLanguageId);
const language = await deleteLanguage(mockLanguageId, mockProductId);
expect(language).toEqual(mockLanguage);
});
});
@@ -115,14 +115,14 @@ describe("Tests for deleteLanguage", () => {
prismaMock.language.delete.mockRejectedValue(errToThrow);
await expect(deleteLanguage(mockEnvironmentId, mockLanguageId)).rejects.toThrow(DatabaseError);
await expect(deleteLanguage(mockLanguageId, mockProductId)).rejects.toThrow(DatabaseError);
});
it("Throws a generic Error for other exceptions", async () => {
const mockErrorMessage = "Mock error message";
prismaMock.language.delete.mockRejectedValue(new Error(mockErrorMessage));
await expect(deleteLanguage(mockEnvironmentId, mockLanguageId)).rejects.toThrow(Error);
await expect(deleteLanguage(mockLanguageId, mockProductId)).rejects.toThrow(Error);
});
});
});