From 803fc488c5e499ab02dec090147dc4e1ecb3c6e8 Mon Sep 17 00:00:00 2001 From: Benny Joo Date: Tue, 5 Nov 2024 11:21:13 -0500 Subject: [PATCH] feat: Add feature to download routing form reports (#17400) * remove unused code * add i18n for some strings in widget * improve UI and add download button to routing forms reporting page * add more margin * add downloadAsCsv util * integrate download button to routing forms report * refactor * address comment * escape comma multiselect items * fix * preserve new lines and wrapping * refactor * ensure fetching all rows --- apps/web/public/static/locales/en/common.json | 4 +- .../react-awesome-query-builder/widgets.tsx | 6 +- .../pages/reporting/[...appPages].tsx | 93 +++++++++++++++++-- .../routing-forms/trpc/report.handler.ts | 3 +- .../routing-forms/trpc/report.schema.ts | 1 + .../insights/filters/Download/index.tsx | 19 +--- packages/features/insights/server/events.ts | 6 -- 7 files changed, 97 insertions(+), 35 deletions(-) diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index 67406948f4..812ba760a5 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -2039,7 +2039,9 @@ "looking_for_more_analytics": "Looking for more analytics?", "looking_for_more_insights": "Looking for more Insights?", "filters": "Filters", - "add_filter": "Add filter", + "add_filter": "Add filter", + "add_rule": "Add rule", + "add_rule_group": "Add rule group", "remove_filters": "Clear all filters", "email_verified": "Email Verified", "select_user": "Select User", diff --git a/packages/app-store/routing-forms/components/react-awesome-query-builder/widgets.tsx b/packages/app-store/routing-forms/components/react-awesome-query-builder/widgets.tsx index 94819da875..dbbd1e985f 100644 --- a/packages/app-store/routing-forms/components/react-awesome-query-builder/widgets.tsx +++ b/packages/app-store/routing-forms/components/react-awesome-query-builder/widgets.tsx @@ -8,6 +8,7 @@ import type { ProviderProps, } from "react-awesome-query-builder"; +import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Button as CalButton, TextField, TextArea } from "@calcom/ui"; import { Icon } from "@calcom/ui"; @@ -224,6 +225,7 @@ function SelectWidget({ listValues, setValue, value, ...remainingProps }: Select } function Button({ config, type, label, onClick, readonly }: ButtonProps) { + const { t } = useLocale(); if (type === "delRule" || type == "delGroup") { return ( +
+ {`${numberOfRows} ${numberOfRows === 1 ? t("row") : t("rows")}`} +
)} + className="border-default bg-subtle mx-3 mb-4 min-w-full table-fixed border-separate border-spacing-0 overflow-hidden rounded-md border"> {headers.current?.map((header, index) => (
@@ -104,7 +181,7 @@ const Result = ({ formId, jsonLogicQuery }: { formId: string; jsonLogicQuery: Js return ( ["fo }} renderBuilder={renderBuilder} /> - + ); }; diff --git a/packages/app-store/routing-forms/trpc/report.handler.ts b/packages/app-store/routing-forms/trpc/report.handler.ts index 4cdd11f8e8..cf5556190f 100644 --- a/packages/app-store/routing-forms/trpc/report.handler.ts +++ b/packages/app-store/routing-forms/trpc/report.handler.ts @@ -39,7 +39,8 @@ const getRows = async ({ ctx: { prisma }, input }: ReportHandlerOptions) => { ? jsonLogicToPrisma(input.jsonLogicQuery) : {}; const skip = input.cursor ?? 0; - const take = 50; + const take = input.limit ? input.limit + 1 : 50; + logger.debug( `Built Prisma where ${JSON.stringify(prismaWhere)} from jsonLogicQuery ${JSON.stringify( input.jsonLogicQuery diff --git a/packages/app-store/routing-forms/trpc/report.schema.ts b/packages/app-store/routing-forms/trpc/report.schema.ts index 2b7799f14b..a7f0270d66 100644 --- a/packages/app-store/routing-forms/trpc/report.schema.ts +++ b/packages/app-store/routing-forms/trpc/report.schema.ts @@ -1,6 +1,7 @@ import z from "zod"; export const ZReportInputSchema = z.object({ + limit: z.number().default(50), formId: z.string(), jsonLogicQuery: z.object({ logic: z.union([z.record(z.any()), z.null()]), diff --git a/packages/features/insights/filters/Download/index.tsx b/packages/features/insights/filters/Download/index.tsx index d6cf4a3bb7..3530ca097b 100644 --- a/packages/features/insights/filters/Download/index.tsx +++ b/packages/features/insights/filters/Download/index.tsx @@ -1,4 +1,5 @@ import { useFilterContext } from "@calcom/features/insights/context/provider"; +import { downloadAsCsv } from "@calcom/lib/csvUtils"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import type { RouterOutputs } from "@calcom/trpc"; import { trpc } from "@calcom/trpc"; @@ -33,23 +34,7 @@ const Download = () => { const handleDownloadClick = async (data: RawData) => { if (!data) return; const { data: csvRaw, filename } = data; - - // Create a Blob from the text data - const blob = new Blob([csvRaw], { type: "text/plain" }); - - // Create an Object URL for the Blob - const url = window.URL.createObjectURL(blob); - - // Create a download link - const a = document.createElement("a"); - a.href = url; - a.download = filename; // Specify the filename - - // Simulate a click event to trigger the download - a.click(); - - // Release the Object URL to free up memory - window.URL.revokeObjectURL(url); + downloadAsCsv(csvRaw, filename); }; return ( diff --git a/packages/features/insights/server/events.ts b/packages/features/insights/server/events.ts index 6930fca490..df22ed7d77 100644 --- a/packages/features/insights/server/events.ts +++ b/packages/features/insights/server/events.ts @@ -7,12 +7,6 @@ import type { RawDataInput } from "./raw-data.schema"; type TimeViewType = "week" | "month" | "year" | "day"; -type DateRange = { - startDate: string; // ISO string format - endDate: string; // ISO string format - formattedDate: string; -}; - type StatusAggregate = { completed: number; rescheduled: number;