fix: Filters do not apply to summary impressions (#2986)

Co-authored-by: Johannes <johannes@formbricks.com>
Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
This commit is contained in:
Piyush Gupta
2024-08-15 19:32:34 +05:30
committed by GitHub
parent 0aebf234f9
commit 2c453bd491
7 changed files with 31 additions and 9 deletions

View File

@@ -13,10 +13,10 @@ const StatCard = ({ label, percentage, value, tooltipText }) => (
<Tooltip>
<TooltipTrigger>
<div className="flex h-full cursor-default flex-col justify-between space-y-2 rounded-xl border border-slate-200 bg-white p-4 text-left shadow-sm">
<p className="text-sm text-slate-600">
<p className="flex items-center gap-1 text-sm text-slate-600">
{label}
{percentage && percentage !== "NaN%" && (
<span className="ml-1 rounded-xl bg-slate-100 px-2 py-1 text-xs">{percentage}</span>
{typeof percentage === "number" && !isNaN(percentage) && (
<span className="ml-1 rounded-xl bg-slate-100 px-2 py-1 text-xs">{percentage}%</span>
)}
</p>
<p className="text-2xl font-bold text-slate-800">{value}</p>
@@ -67,13 +67,13 @@ export const SummaryMetadata = ({ setShowDropOffs, showDropOffs, surveySummary }
/>
<StatCard
label="Starts"
percentage={`${Math.round(startsPercentage)}%`}
percentage={Math.round(startsPercentage) > 100 ? null : Math.round(startsPercentage)}
value={totalResponses === 0 ? <span>-</span> : totalResponses}
tooltipText="Number of times the survey has been started."
/>
<StatCard
label="Completed"
percentage={`${Math.round(completedPercentage)}%`}
percentage={Math.round(completedPercentage) > 100 ? null : Math.round(completedPercentage)}
value={completedResponses === 0 ? <span>-</span> : completedResponses}
tooltipText="Number of times the survey has been completed."
/>

View File

@@ -110,7 +110,7 @@ test.describe("JS Package Test", async () => {
expect(impressionsCount).toEqual("Impressions\n\n1");
await expect(page.getByRole("link", { name: "Responses (1)" })).toBeVisible();
await expect(page.getByRole("button", { name: "Completed100%" })).toBeVisible();
await expect(page.getByRole("button", { name: "Completed 100%" })).toBeVisible();
await expect(page.getByText("1 Responses", { exact: true }).first()).toBeVisible();
await expect(page.getByText("CTR100%")).toBeVisible();

View File

@@ -0,0 +1,2 @@
-- AddForeignKey
ALTER TABLE "Display" ADD CONSTRAINT "Display_responseId_fkey" FOREIGN KEY ("responseId") REFERENCES "Response"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -132,6 +132,7 @@ model Response {
// singleUseId, used to prevent multiple responses
singleUseId String?
language String?
display Display?
@@unique([surveyId, singleUseId])
@@index([surveyId, createdAt]) // to determine monthly response count
@@ -199,6 +200,7 @@ model Display {
person Person? @relation(fields: [personId], references: [id], onDelete: Cascade)
personId String?
responseId String? @unique
response Response? @relation(fields: [responseId], references: [id], onDelete: Cascade)
status DisplayStatus?
@@index([surveyId])

View File

@@ -84,7 +84,11 @@ export const updateDisplay = async (
},
}),
...(displayInput.responseId && {
responseId: displayInput.responseId,
response: {
connect: {
id: displayInput.responseId,
},
},
}),
};
const display = await prisma.display.update({
@@ -236,6 +240,12 @@ export const getDisplayCountBySurveyId = reactCache(
lte: filters.createdAt.max,
},
}),
...(filters &&
filters.responseIds && {
responseId: {
in: filters.responseIds,
},
}),
},
});
return displayCount;

View File

@@ -457,8 +457,12 @@ export const getSurveySummary = reactCache(
}
const batchSize = 3000;
const responseCount = await getResponseCountBySurveyId(surveyId, filterCriteria);
const pages = Math.ceil(responseCount / batchSize);
const totalResponseCount = await getResponseCountBySurveyId(surveyId);
const filteredResponseCount = await getResponseCountBySurveyId(surveyId, filterCriteria);
const hasFilter = totalResponseCount !== filteredResponseCount;
const pages = Math.ceil(filteredResponseCount / batchSize);
const responsesArray = await Promise.all(
Array.from({ length: pages }, (_, i) => {
@@ -467,8 +471,11 @@ export const getSurveySummary = reactCache(
);
const responses = responsesArray.flat();
const responseIds = hasFilter ? responses.map((response) => response.id) : [];
const displayCount = await getDisplayCountBySurveyId(surveyId, {
createdAt: filterCriteria?.createdAt,
...(hasFilter && { responseIds }),
});
const dropOff = getSurveySummaryDropOff(survey, responses, displayCount);

View File

@@ -42,6 +42,7 @@ export const ZDisplayFilters = z.object({
max: z.date().optional(),
})
.optional(),
responseIds: z.array(z.string().cuid()).optional(),
});
export type TDisplayFilters = z.infer<typeof ZDisplayFilters>;