diff --git a/.cursor/rules/testing-patterns.mdc b/.cursor/rules/testing-patterns.mdc index b87c092ac5..b79a9b01da 100644 --- a/.cursor/rules/testing-patterns.mdc +++ b/.cursor/rules/testing-patterns.mdc @@ -90,7 +90,7 @@ When testing hooks that use React Context: vi.mocked(useResponseFilter).mockReturnValue({ selectedFilter: { filter: [], - onlyComplete: false, + responseStatus: "all", }, setSelectedFilter: vi.fn(), selectedOptions: { diff --git a/apps/web/app/(app)/environments/[environmentId]/components/ResponseFilterContext.test.tsx b/apps/web/app/(app)/environments/[environmentId]/components/ResponseFilterContext.test.tsx index 764e1c7043..c78d71799c 100644 --- a/apps/web/app/(app)/environments/[environmentId]/components/ResponseFilterContext.test.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/components/ResponseFilterContext.test.tsx @@ -28,7 +28,7 @@ const TestComponent = () => { return (
-
{selectedFilter.onlyComplete.toString()}
+
{selectedFilter.responseStatus}
{selectedFilter.filter.length}
{selectedOptions.questionOptions.length}
{selectedOptions.questionFilterOptions.length}
@@ -44,7 +44,7 @@ const TestComponent = () => { filterType: { filterValue: "value1", filterComboBoxValue: "option1" }, }, ], - onlyComplete: true, + responseStatus: "complete", }) }> Update Filter @@ -81,7 +81,7 @@ describe("ResponseFilterContext", () => { ); - expect(screen.getByTestId("onlyComplete").textContent).toBe("false"); + expect(screen.getByTestId("responseStatus").textContent).toBe("all"); expect(screen.getByTestId("filterLength").textContent).toBe("0"); expect(screen.getByTestId("questionOptionsLength").textContent).toBe("0"); expect(screen.getByTestId("questionFilterOptionsLength").textContent).toBe("0"); @@ -99,7 +99,7 @@ describe("ResponseFilterContext", () => { const updateButton = screen.getByText("Update Filter"); await userEvent.click(updateButton); - expect(screen.getByTestId("onlyComplete").textContent).toBe("true"); + expect(screen.getByTestId("responseStatus").textContent).toBe("complete"); expect(screen.getByTestId("filterLength").textContent).toBe("1"); }); diff --git a/apps/web/app/(app)/environments/[environmentId]/components/ResponseFilterContext.tsx b/apps/web/app/(app)/environments/[environmentId]/components/ResponseFilterContext.tsx index ec62057383..850288a0e2 100644 --- a/apps/web/app/(app)/environments/[environmentId]/components/ResponseFilterContext.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/components/ResponseFilterContext.tsx @@ -16,9 +16,11 @@ export interface FilterValue { }; } +export type TResponseStatus = "all" | "complete" | "partial"; + export interface SelectedFilterValue { filter: FilterValue[]; - onlyComplete: boolean; + responseStatus: TResponseStatus; } interface SelectedFilterOptions { @@ -47,7 +49,7 @@ const ResponseFilterProvider = ({ children }: { children: React.ReactNode }) => // state holds the filter selected value const [selectedFilter, setSelectedFilter] = useState({ filter: [], - onlyComplete: false, + responseStatus: "all", }); // state holds all the options of the responses fetched const [selectedOptions, setSelectedOptions] = useState({ @@ -67,7 +69,7 @@ const ResponseFilterProvider = ({ children }: { children: React.ReactNode }) => }); setSelectedFilter({ filter: [], - onlyComplete: false, + responseStatus: "all", }); }, []); diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.test.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.test.tsx index 885e7cf62b..8f364fc122 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.test.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.test.tsx @@ -191,7 +191,7 @@ const mockSurvey = { variables: [], } as unknown as TSurvey; -const mockSelectedFilter = { filter: [], onlyComplete: false }; +const mockSelectedFilter = { filter: [], responseStatus: "all" }; const mockSetSelectedFilter = vi.fn(); const defaultProps = { @@ -309,17 +309,13 @@ describe("SummaryList", () => { test("renders EmptySpaceFiller when responseCount is 0 and summary is not empty (no responses match filter)", () => { const summaryWithItem = [createMockQuestionSummary("q1", TSurveyQuestionTypeEnum.OpenText)]; - render( - - ); + render(); expect(screen.getByText("Mocked EmptySpaceFiller")).toBeInTheDocument(); }); test("renders EmptySpaceFiller when responseCount is 0 and totalResponseCount is 0 (no responses at all)", () => { const summaryWithItem = [createMockQuestionSummary("q1", TSurveyQuestionTypeEnum.OpenText)]; - render( - - ); + render(); expect(screen.getByText("Mocked EmptySpaceFiller")).toBeInTheDocument(); }); @@ -397,7 +393,7 @@ describe("SummaryList", () => { }, }, ], - onlyComplete: false, + responseStatus: "all", }); // Ensure vi.mocked(toast.success) refers to the spy from the named export expect(vi.mocked(toast).success).toHaveBeenCalledWith("Custom add message", { duration: 5000 }); @@ -425,7 +421,7 @@ describe("SummaryList", () => { }, }; vi.mocked(useResponseFilter).mockReturnValue({ - selectedFilter: { filter: [existingFilter], onlyComplete: false }, + selectedFilter: { filter: [existingFilter], responseStatus: "all" }, setSelectedFilter: mockSetSelectedFilter, resetFilter: vi.fn(), } as any); @@ -454,7 +450,7 @@ describe("SummaryList", () => { }, }, ], - onlyComplete: false, + responseStatus: "all", }); expect(vi.mocked(toast.success)).toHaveBeenCalledWith( "environments.surveys.summary.filter_updated_successfully", diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx index f6166a8b20..f3df77903d 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx @@ -92,7 +92,7 @@ export const SummaryList = ({ summary, environment, responseCount, survey, local setSelectedFilter({ filter: [...filterObject.filter], - onlyComplete: filterObject.onlyComplete, + responseStatus: filterObject.responseStatus, }); }; diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/QuestionFilterComboBox.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/QuestionFilterComboBox.tsx index 675cb80954..44ee4537c4 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/QuestionFilterComboBox.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/QuestionFilterComboBox.tsx @@ -197,7 +197,7 @@ export const QuestionFilterComboBox = ({
{open && ( -
+
{open && ( -
+
{t("common.no_result_found")} {options?.map((data) => ( diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/ResponseFilter.test.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/ResponseFilter.test.tsx index 8353818ef0..e02ee48108 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/ResponseFilter.test.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/ResponseFilter.test.tsx @@ -30,6 +30,45 @@ vi.mock("@formkit/auto-animate/react", () => ({ useAutoAnimate: () => [[vi.fn()]], })); +// Mock the Select components +const mockOnValueChange = vi.fn(); +vi.mock("@/modules/ui/components/select", () => ({ + Select: ({ children, onValueChange, defaultValue }) => { + // Store the onValueChange callback for testing + mockOnValueChange.mockImplementation(onValueChange); + return ( +
+ {children} +
+ ); + }, + SelectTrigger: ({ children, className }) => ( + + ), + SelectValue: () => environments.surveys.filter.complete_and_partial_responses, + SelectContent: ({ children }) =>
{children}
, + SelectItem: ({ value, children, ...props }) => ( +
mockOnValueChange(value)} + onKeyDown={(e) => e.key === "Enter" && mockOnValueChange(value)} + role="option" + tabIndex={0} + {...props}> + {children} +
+ ), +})); + vi.mock("./QuestionsComboBox", () => ({ QuestionsComboBox: ({ onChangeValue }) => (
@@ -67,7 +106,7 @@ describe("ResponseFilter", () => { const mockSelectedFilter = { filter: [], - onlyComplete: false, + responseStatus: "all", }; const mockSelectedOptions = { @@ -145,7 +184,7 @@ describe("ResponseFilter", () => { expect( screen.getByText("environments.surveys.summary.show_all_responses_that_match") ).toBeInTheDocument(); - expect(screen.getByText("environments.surveys.summary.only_completed")).toBeInTheDocument(); + expect(screen.getByTestId("select-trigger")).toBeInTheDocument(); }); test("fetches filter data when opened", async () => { @@ -160,7 +199,7 @@ describe("ResponseFilter", () => { test("handles adding new filter", async () => { // Start with an empty filter vi.mocked(useResponseFilter).mockReturnValue({ - selectedFilter: { filter: [], onlyComplete: false }, + selectedFilter: { filter: [], responseStatus: "all" }, setSelectedFilter: mockSetSelectedFilter, selectedOptions: mockSelectedOptions, setSelectedOptions: mockSetSelectedOptions, @@ -178,14 +217,38 @@ describe("ResponseFilter", () => { expect(screen.getByTestId("questions-combo-box")).toBeInTheDocument(); }); - test("handles only complete checkbox toggle", async () => { + test("handles response status filter change to complete", async () => { render(); await userEvent.click(screen.getByText("Filter")); - await userEvent.click(screen.getByRole("checkbox")); + + // Simulate selecting "complete" by calling the mock function + mockOnValueChange("complete"); + await userEvent.click(screen.getByText("common.apply_filters")); - expect(mockSetSelectedFilter).toHaveBeenCalledWith({ filter: [], onlyComplete: true }); + expect(mockSetSelectedFilter).toHaveBeenCalledWith( + expect.objectContaining({ + responseStatus: "complete", + }) + ); + }); + + test("handles response status filter change to partial", async () => { + render(); + + await userEvent.click(screen.getByText("Filter")); + + // Simulate selecting "partial" by calling the mock function + mockOnValueChange("partial"); + + await userEvent.click(screen.getByText("common.apply_filters")); + + expect(mockSetSelectedFilter).toHaveBeenCalledWith( + expect.objectContaining({ + responseStatus: "partial", + }) + ); }); test("handles selecting question and filter options", async () => { @@ -199,7 +262,7 @@ describe("ResponseFilter", () => { filterType: { filterComboBoxValue: undefined, filterValue: undefined }, }, ], - onlyComplete: false, + responseStatus: "all", }, setSelectedFilter: setSelectedFilterMock, selectedOptions: mockSelectedOptions, @@ -228,6 +291,6 @@ describe("ResponseFilter", () => { await userEvent.click(screen.getByText("Filter")); await userEvent.click(screen.getByText("common.clear_all")); - expect(mockSetSelectedFilter).toHaveBeenCalledWith({ filter: [], onlyComplete: false }); + expect(mockSetSelectedFilter).toHaveBeenCalledWith({ filter: [], responseStatus: "all" }); }); }); diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/ResponseFilter.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/ResponseFilter.tsx index d65758ac16..1bd4102606 100644 --- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/ResponseFilter.tsx +++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/ResponseFilter.tsx @@ -2,17 +2,23 @@ import { SelectedFilterValue, + TResponseStatus, useResponseFilter, } from "@/app/(app)/environments/[environmentId]/components/ResponseFilterContext"; import { getSurveyFilterDataAction } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/actions"; import { QuestionFilterComboBox } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/QuestionFilterComboBox"; import { generateQuestionAndFilterOptions } from "@/app/lib/surveys/surveys"; import { Button } from "@/modules/ui/components/button"; -import { Checkbox } from "@/modules/ui/components/checkbox"; import { Popover, PopoverContent, PopoverTrigger } from "@/modules/ui/components/popover"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/modules/ui/components/select"; import { useAutoAnimate } from "@formkit/auto-animate/react"; import { useTranslate } from "@tolgee/react"; -import clsx from "clsx"; import { ChevronDown, ChevronUp, Plus, TrashIcon } from "lucide-react"; import React, { useEffect, useState } from "react"; import { TSurvey, TSurveyQuestionTypeEnum } from "@formbricks/types/surveys/types"; @@ -72,7 +78,7 @@ export const ResponseFilter = ({ survey }: ResponseFilterProps) => { )?.filterOptions[0], }, }; - setFilterValue({ filter: [...filterValue.filter], onlyComplete: filterValue.onlyComplete }); + setFilterValue({ filter: [...filterValue.filter], responseStatus: filterValue.responseStatus }); } else { // Update the existing value at the specified index filterValue.filter[index].questionType = value; @@ -93,7 +99,7 @@ export const ResponseFilter = ({ survey }: ResponseFilterProps) => { // keep the filter if questionType is selected and filterComboBoxValue is selected return s.questionType.hasOwnProperty("label") && s.filterType.filterComboBoxValue?.length; }), - onlyComplete: filterValue.onlyComplete, + responseStatus: filterValue.responseStatus, }); }; @@ -120,8 +126,8 @@ export const ResponseFilter = ({ survey }: ResponseFilterProps) => { }; const handleClearAllFilters = () => { - setFilterValue((filterValue) => ({ ...filterValue, filter: [] })); - setSelectedFilter((selectedFilters) => ({ ...selectedFilters, filter: [] })); + setFilterValue((filterValue) => ({ ...filterValue, filter: [], responseStatus: "all" })); + setSelectedFilter((selectedFilters) => ({ ...selectedFilters, filter: [], responseStatus: "all" })); setIsOpen(false); }; @@ -158,8 +164,8 @@ export const ResponseFilter = ({ survey }: ResponseFilterProps) => { setFilterValue({ ...filterValue }); }; - const handleCheckOnlyComplete = (checked: boolean) => { - setFilterValue({ ...filterValue, onlyComplete: checked }); + const handleResponseStatusChange = (responseStatus: TResponseStatus) => { + setFilterValue({ ...filterValue, responseStatus }); }; // remove the filter which has already been selected @@ -203,8 +209,9 @@ export const ResponseFilter = ({ survey }: ResponseFilterProps) => { -
+ className="w-[300px] border-slate-200 bg-slate-100 p-6 sm:w-[400px] md:w-[750px] lg:w-[1000px]" + onOpenAutoFocus={(event) => event.preventDefault()}> +

{t("environments.surveys.summary.show_all_responses_that_match")}

@@ -212,16 +219,24 @@ export const ResponseFilter = ({ survey }: ResponseFilterProps) => { {t("environments.surveys.summary.show_all_responses_where")}

- - { - typeof checked === "boolean" && handleCheckOnlyComplete(checked); +
diff --git a/apps/web/app/lib/surveys/surveys.test.ts b/apps/web/app/lib/surveys/surveys.test.ts index 0e055e26b1..2db92b55e2 100644 --- a/apps/web/app/lib/surveys/surveys.test.ts +++ b/apps/web/app/lib/surveys/surveys.test.ts @@ -320,7 +320,7 @@ describe("surveys", () => { test("should return empty filters when no selections", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [], }; @@ -331,7 +331,7 @@ describe("surveys", () => { test("should filter by completed responses", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: true, + responseStatus: "complete", filter: [], }; @@ -342,7 +342,7 @@ describe("surveys", () => { test("should filter by date range", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [], }; @@ -355,7 +355,7 @@ describe("surveys", () => { test("should filter by tags", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { type: "Tags", label: "Tag 1", id: "tag1" }, @@ -376,7 +376,7 @@ describe("surveys", () => { test("should filter by open text questions", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { @@ -397,7 +397,7 @@ describe("surveys", () => { test("should filter by address questions", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { @@ -418,7 +418,7 @@ describe("surveys", () => { test("should filter by contact info questions", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { @@ -439,7 +439,7 @@ describe("surveys", () => { test("should filter by ranking questions", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { @@ -460,7 +460,7 @@ describe("surveys", () => { test("should filter by multiple choice single questions", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { @@ -481,7 +481,7 @@ describe("surveys", () => { test("should filter by multiple choice multi questions", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { @@ -502,7 +502,7 @@ describe("surveys", () => { test("should filter by NPS questions with different operations", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { @@ -523,7 +523,7 @@ describe("surveys", () => { test("should filter by rating questions with less than operation", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { @@ -544,7 +544,7 @@ describe("surveys", () => { test("should filter by CTA questions", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { @@ -565,7 +565,7 @@ describe("surveys", () => { test("should filter by consent questions", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { @@ -586,7 +586,7 @@ describe("surveys", () => { test("should filter by picture selection questions", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { @@ -607,7 +607,7 @@ describe("surveys", () => { test("should filter by matrix questions", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { @@ -628,7 +628,7 @@ describe("surveys", () => { test("should filter by hidden fields", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { type: "Hidden Fields", label: "plan", id: "plan" }, @@ -644,7 +644,7 @@ describe("surveys", () => { test("should filter by attributes", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { type: "Attributes", label: "role", id: "role" }, @@ -660,7 +660,7 @@ describe("surveys", () => { test("should filter by other filters", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { type: "Other Filters", label: "Language", id: "language" }, @@ -676,7 +676,7 @@ describe("surveys", () => { test("should filter by meta fields", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: false, + responseStatus: "all", filter: [ { questionType: { type: "Meta", label: "source", id: "source" }, @@ -692,7 +692,7 @@ describe("surveys", () => { test("should handle multiple filters together", () => { const selectedFilter: SelectedFilterValue = { - onlyComplete: true, + responseStatus: "complete", filter: [ { questionType: { diff --git a/apps/web/app/lib/surveys/surveys.ts b/apps/web/app/lib/surveys/surveys.ts index 5e5ee6d84f..065f8c18c4 100644 --- a/apps/web/app/lib/surveys/surveys.ts +++ b/apps/web/app/lib/surveys/surveys.ts @@ -242,8 +242,10 @@ export const getFormattedFilters = ( }); // for completed responses - if (selectedFilter.onlyComplete) { + if (selectedFilter.responseStatus === "complete") { filters["finished"] = true; + } else if (selectedFilter.responseStatus === "partial") { + filters["finished"] = false; } // for date range responses diff --git a/apps/web/locales/de-DE.json b/apps/web/locales/de-DE.json index 0629ef981e..2252b9471f 100644 --- a/apps/web/locales/de-DE.json +++ b/apps/web/locales/de-DE.json @@ -510,13 +510,11 @@ "create_action": "Aktion erstellen", "css_selector": "CSS-Selektor", "delete_action_text": "Bist Du sicher, dass Du diese Aktion löschen möchtest? Dadurch wird diese Aktion auch als Auslöser aus all deinen Umfragen entfernt.", - "display_name": "Anzeigename", "does_not_contain": "Enthält nicht", "does_not_exactly_match": "Stimmt nicht genau überein", "eg_clicked_download": "z.B. 'Herunterladen' geklickt", "eg_download_cta_click_on_home": "z.B. Download-CTA-Klick auf der Startseite", "eg_install_app": "z.B. App installieren", - "eg_user_clicked_download_button": "z.B. Benutzer hat auf 'Herunterladen' geklickt", "ends_with": "endet mit", "enter_a_url_to_see_if_a_user_visiting_it_would_be_tracked": "Teste eine URL, um zu sehen, ob der Nutzer deine Umfrage sehen würde.", "enter_url": "z.B. https://app.com/dashboard", @@ -1616,6 +1614,11 @@ "zip": "Postleitzahl" }, "error_deleting_survey": "Beim Löschen der Umfrage ist ein Fehler aufgetreten", + "filter": { + "complete_and_partial_responses": "Vollständige und Teilantworten", + "complete_responses": "Vollständige Antworten", + "partial_responses": "Teilantworten" + }, "new_survey": "Neue Umfrage", "no_surveys_created_yet": "Noch keine Umfragen erstellt", "open_options": "Optionen öffnen", diff --git a/apps/web/locales/en-US.json b/apps/web/locales/en-US.json index b123af8e3f..c38c9f128c 100644 --- a/apps/web/locales/en-US.json +++ b/apps/web/locales/en-US.json @@ -510,13 +510,11 @@ "create_action": "Create action", "css_selector": "CSS Selector", "delete_action_text": "Are you sure you want to delete this action? This also removes this action as a trigger from all your surveys.", - "display_name": "Display name", "does_not_contain": "Does not contain", "does_not_exactly_match": "Does not exactly match", "eg_clicked_download": "E.g. Clicked Download", "eg_download_cta_click_on_home": "e.g. download_cta_click_on_home", "eg_install_app": "E.g. Install App", - "eg_user_clicked_download_button": "E.g. User clicked Download Button", "ends_with": "Ends with", "enter_a_url_to_see_if_a_user_visiting_it_would_be_tracked": "Enter a URL to see if a user visiting it would be tracked.", "enter_url": "e.g. https://app.com/dashboard", @@ -1616,6 +1614,11 @@ "zip": "Zip" }, "error_deleting_survey": "An error occured while deleting survey", + "filter": { + "complete_and_partial_responses": "Complete and partial responses", + "complete_responses": "Complete responses", + "partial_responses": "Partial responses" + }, "new_survey": "New Survey", "no_surveys_created_yet": "No surveys created yet", "open_options": "Open options", diff --git a/apps/web/locales/fr-FR.json b/apps/web/locales/fr-FR.json index 429ca3c62a..655aaa9d25 100644 --- a/apps/web/locales/fr-FR.json +++ b/apps/web/locales/fr-FR.json @@ -510,13 +510,11 @@ "create_action": "Créer une action", "css_selector": "Sélecteur CSS", "delete_action_text": "Êtes-vous sûr de vouloir supprimer cette action ? Cela supprime également cette action en tant que déclencheur de toutes vos enquêtes.", - "display_name": "Nom d'affichage", "does_not_contain": "Ne contient pas", "does_not_exactly_match": "Ne correspond pas exactement", "eg_clicked_download": "Par exemple, cliqué sur Télécharger", "eg_download_cta_click_on_home": "Par exemple, cliquez sur le CTA de téléchargement sur la page d'accueil", "eg_install_app": "Par exemple, installer l'application", - "eg_user_clicked_download_button": "Par exemple, l'utilisateur a cliqué sur le bouton de téléchargement.", "ends_with": "Se termine par", "enter_a_url_to_see_if_a_user_visiting_it_would_be_tracked": "Saisissez une URL pour voir si un utilisateur la visitant serait suivi.", "enter_url": "par exemple https://app.com/dashboard", @@ -1616,6 +1614,11 @@ "zip": "Zip" }, "error_deleting_survey": "Une erreur est survenue lors de la suppression de l'enquête.", + "filter": { + "complete_and_partial_responses": "Réponses complètes et partielles", + "complete_responses": "Réponses complètes", + "partial_responses": "Réponses partielles" + }, "new_survey": "Nouveau Sondage", "no_surveys_created_yet": "Aucun sondage créé pour le moment", "open_options": "Ouvrir les options", diff --git a/apps/web/locales/pt-BR.json b/apps/web/locales/pt-BR.json index 7041064899..8b1902f793 100644 --- a/apps/web/locales/pt-BR.json +++ b/apps/web/locales/pt-BR.json @@ -510,13 +510,11 @@ "create_action": "criar ação", "css_selector": "Seletor CSS", "delete_action_text": "Tem certeza de que quer deletar essa ação? Isso também vai remover essa ação como gatilho de todas as suas pesquisas.", - "display_name": "Nome de exibição", "does_not_contain": "não contém", "does_not_exactly_match": "Não bate exatamente", "eg_clicked_download": "Por exemplo, clicou em baixar", "eg_download_cta_click_on_home": "e.g. download_cta_click_on_home", "eg_install_app": "Ex: Instalar App", - "eg_user_clicked_download_button": "Por exemplo, usuário clicou no botão de download", "ends_with": "Termina com", "enter_a_url_to_see_if_a_user_visiting_it_would_be_tracked": "Digite uma URL para ver se um usuário que a visita seria rastreado.", "enter_url": "ex.: https://app.com/dashboard", @@ -1616,6 +1614,11 @@ "zip": "Fecho éclair" }, "error_deleting_survey": "Ocorreu um erro ao deletar a pesquisa", + "filter": { + "complete_and_partial_responses": "Respostas completas e parciais", + "complete_responses": "Respostas completas", + "partial_responses": "Respostas parciais" + }, "new_survey": "Nova Pesquisa", "no_surveys_created_yet": "Ainda não foram criadas pesquisas", "open_options": "Abre opções", diff --git a/apps/web/locales/pt-PT.json b/apps/web/locales/pt-PT.json index 3f0f7541fa..e39b993600 100644 --- a/apps/web/locales/pt-PT.json +++ b/apps/web/locales/pt-PT.json @@ -510,13 +510,11 @@ "create_action": "Criar ação", "css_selector": "Seletor CSS", "delete_action_text": "Tem a certeza de que deseja eliminar esta ação? Isto também remove esta ação como um gatilho de todos os seus inquéritos.", - "display_name": "Nome de exibição", "does_not_contain": "Não contém", "does_not_exactly_match": "Não corresponde exatamente", "eg_clicked_download": "Por exemplo, Clicou em Descarregar", "eg_download_cta_click_on_home": "por exemplo, descarregar_cta_clicar_em_home", "eg_install_app": "Ex. Instalar App", - "eg_user_clicked_download_button": "Por exemplo, Utilizador clicou no Botão Descarregar", "ends_with": "Termina com", "enter_a_url_to_see_if_a_user_visiting_it_would_be_tracked": "Introduza um URL para ver se um utilizador que o visita seria rastreado.", "enter_url": "por exemplo, https://app.com/dashboard", @@ -1616,6 +1614,11 @@ "zip": "Comprimir" }, "error_deleting_survey": "Ocorreu um erro ao eliminar o questionário", + "filter": { + "complete_and_partial_responses": "Respostas completas e parciais", + "complete_responses": "Respostas completas", + "partial_responses": "Respostas parciais" + }, "new_survey": "Novo inquérito", "no_surveys_created_yet": "Ainda não foram criados questionários", "open_options": "Abrir opções", diff --git a/apps/web/locales/zh-Hant-TW.json b/apps/web/locales/zh-Hant-TW.json index 6b08d99e9c..b324e9f773 100644 --- a/apps/web/locales/zh-Hant-TW.json +++ b/apps/web/locales/zh-Hant-TW.json @@ -510,13 +510,11 @@ "create_action": "建立操作", "css_selector": "CSS 選取器", "delete_action_text": "您確定要刪除此操作嗎?這也會從您的所有問卷中移除此操作作為觸發器。", - "display_name": "顯示名稱", "does_not_contain": "不包含", "does_not_exactly_match": "不完全相符", "eg_clicked_download": "例如,點擊下載", "eg_download_cta_click_on_home": "例如,download_cta_click_on_home", "eg_install_app": "例如,安裝應用程式", - "eg_user_clicked_download_button": "例如,使用者點擊了下載按鈕", "ends_with": "結尾為", "enter_a_url_to_see_if_a_user_visiting_it_would_be_tracked": "輸入網址以查看造訪該網址的使用者是否會被追蹤。", "enter_url": "例如 https://app.com/dashboard", @@ -1616,6 +1614,11 @@ "zip": "郵遞區號" }, "error_deleting_survey": "刪除問卷時發生錯誤", + "filter": { + "complete_and_partial_responses": "完整 和 部分 回應", + "complete_responses": "完整回應", + "partial_responses": "部分回應" + }, "new_survey": "新增問卷", "no_surveys_created_yet": "尚未建立任何問卷", "open_options": "開啟選項", diff --git a/apps/web/modules/ui/components/command/index.tsx b/apps/web/modules/ui/components/command/index.tsx index ee76b713a0..7ad108bd44 100644 --- a/apps/web/modules/ui/components/command/index.tsx +++ b/apps/web/modules/ui/components/command/index.tsx @@ -60,7 +60,7 @@ function CommandInput({ ...props }: React.ComponentProps & { hidden?: boolean }) { return ( -
+