mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-30 02:10:12 -06:00
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:
@@ -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."
|
||||
/>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
@@ -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])
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>;
|
||||
|
||||
Reference in New Issue
Block a user