diff --git a/src/components/input/argument_input/ArgumentInput.jsx b/src/components/input/argument_input/ArgumentInput.jsx index aafafdb1..58b143ae 100644 --- a/src/components/input/argument_input/ArgumentInput.jsx +++ b/src/components/input/argument_input/ArgumentInput.jsx @@ -18,7 +18,11 @@ import React, { useState, useEffect, useRef, lazy, Suspense } from "react"; import { FormattedMessage } from "react-intl"; import { useIntl } from "react-intl"; import { useLocation } from "react-router"; -const SideModal = lazy(() => import("@logora/debate/modal/side_modal").then(m => ({ default: m.SideModal }))); +const SideModal = lazy(() => + import("@logora/debate/modal/side_modal").then((m) => ({ + default: m.SideModal, + })), +); import cx from "classnames"; import styles from "./ArgumentInput.module.scss"; @@ -27,7 +31,6 @@ export const ArgumentInput = ({ avatarSize = 48, disabled = false, positions = [], - disabledPositions = [], groupId, groupName, groupType, @@ -207,7 +210,6 @@ export const ArgumentInput = ({ onChooseSide={handleChooseSide} positions={positions} title={groupName} - disabledPositions={!isReply && disabledPositions} isNeutral={ savedArgument && savedArgument.groupId == groupId && @@ -226,8 +228,7 @@ export const ArgumentInput = ({ if ( !positions || positions?.length === 0 || - (!disabledPositions?.find((pos) => pos?.id === userPositionId) && - userPositionId) || + userPositionId || (isEditorOrModerator && isReply) ) { submitArgument(isReply && isEditorOrModerator && positions[0]?.id); @@ -289,64 +290,81 @@ export const ArgumentInput = ({ setSavedArgument(argumentToSave); } resetInputs(); - api.create("messages", data).then((response) => { - if (response.data.success) { - if (parentId) { - onSubmit(response.data.data.resource); - toast( - intl.formatMessage({ - id: "alert.argument_create", - defaultMessage: "Your contribution has been sent !", - }), - { - type: "success", - points: intl.formatMessage({ - id: "alert.reply_gain", - defaultMessage: " ", + api + .create("messages", data) + .then((response) => { + if (response.data.success) { + if (parentId) { + onSubmit(response.data.data.resource); + toast( + intl.formatMessage({ + id: "alert.argument_create", + defaultMessage: "Your contribution has been sent !", }), - }, - ); - } else { - const argument = response.data.data.resource; - let listId = argumentListId; - if (userPosition && !isMobile) { - listId = `argumentList${argument.position.id}`; + { + type: "success", + points: intl.formatMessage({ + id: "alert.reply_gain", + defaultMessage: " ", + }), + }, + ); + } else { + const argument = response.data.data.resource; + let listId = argumentListId; + if (userPosition && !isMobile) { + listId = `argumentList${argument.position.id}`; + } + onSubmit?.( + argumentContent, + positions.find((pos) => pos.id === userPosition) || null, + ); + list.add(listId, [argument]); + toast( + intl.formatMessage({ + id: "alert.argument_create", + defaultMessage: "Your contribution has been sent !", + }), + { + type: "success", + points: intl.formatMessage({ + id: "alert.argument_create_gain", + defaultMessage: "Up to 10 eloquence points", + }), + category: "ARGUMENT", + contentKey: + currentUser.messages_count === 2 + ? "alert.third_argument" + : "alert.first_argument", + }, + ); } - onSubmit?.( - argumentContent, - positions.find((pos) => pos.id === userPosition) || null, - ); - list.add(listId, [argument]); - toast( - intl.formatMessage({ - id: "alert.argument_create", - defaultMessage: "Your contribution has been sent !", - }), - { - type: "success", - points: intl.formatMessage({ - id: "alert.argument_create_gain", - defaultMessage: "Up to 10 eloquence points", + if (typeof window !== "undefined") { + window.dispatchEvent( + new CustomEvent("logora:user_content:created", { + detail: { + content: response.data.data?.resource, + }, }), - category: "ARGUMENT", - contentKey: - currentUser.messages_count === 2 - ? "alert.third_argument" - : "alert.first_argument", - }, - ); + ); + } } - if (typeof window !== "undefined") { - window.dispatchEvent( - new CustomEvent("logora:user_content:created", { - detail: { - content: response.data.data?.resource, - }, - }), + }) + .catch((error) => { + if (error?.response?.status === 429) { + toast( + error?.response?.data?.error?.detail || + intl.formatMessage({ + id: "alert.argument_limit", + defaultMessage: + "You have reached your daily contribution limit for this debate.", + }), + { type: "error" }, ); + } else { + console.error(error); } - } - }); + }); } }; @@ -365,9 +383,7 @@ export const ArgumentInput = ({ let listId = argumentListId; if (editElement?.is_reply || isReply) { const replyListId = - editElement?.message_id || - editElement?.reply_to_id || - parentId; + editElement?.message_id || editElement?.reply_to_id || parentId; if (replyListId) { listId = `argument_${replyListId}_reply_list`; } @@ -416,22 +432,6 @@ export const ArgumentInput = ({ } }; - const displayArgumentLimitWarning = () => { - const disabledPosition = disabledPositions.find( - (pos) => pos.id === userPositionId, - ); - if (disabledPosition) { - return intl.formatMessage( - { - id: "info.argument_side_limit", - defaultMessage: - "You have reached the argument limit (10) for position {position}.", - }, - { position: disabledPosition.name }, - ); - } - }; - return (
{disabled && ( @@ -568,27 +568,6 @@ export const ArgumentInput = ({ ))}
)} - {inputActivation && - disabledPositions?.find( - (pos) => pos.id === userPositionId, - ) && ( -
- -
- {displayArgumentLimitWarning()} -
-
- )} {inputActivation && userGuideUrl && !hideUserGuideLink && (
( { groupId={debate.id} groupName={debate.name} positions={debate.positions} - disabledPositions={[]} listId={"argumentList"} positionId={debate.positions[0].id} hideSourceAction={false} @@ -168,7 +167,6 @@ describe("ArgumentInput", () => { groupId={debate.id} groupName={debate.name} positions={debate.positions} - disabledPositions={[]} listId={"argumentList"} positionId={debate.positions[0].id} hideSourceAction={false} @@ -213,7 +211,6 @@ describe("ArgumentInput", () => { groupId={debate.id} groupName={debate.name} positions={debate.positions} - disabledPositions={[]} disabled listId={"argumentList"} positionId={debate.positions[0].id} @@ -236,60 +233,6 @@ describe("ArgumentInput", () => { expect(queryByText("Debate is closed")).toBeInTheDocument(); }); - it("should display side modal if the disabledPositions is set", async () => { - const { queryByText, getByText, getByTestId } = render( - - - - - - - - - - - {}} - groupId={debate.id} - groupName={debate.name} - positions={debate.positions} - disabledPositions={[ - { - id: debate.positions[0].id, - name: debate.positions[0].name, - }, - ]} - listId={"argumentList"} - positionId={debate.positions[0].id} - hideSourceAction - avatarSize={48} - placeholder={"Add an argument..."} - /> - - - - - - - - - - , - ); - - expect(queryByText("Add an argument...")).toBeInTheDocument(); - expect(queryByText(debate.positions[0].name)).toBeInTheDocument(); - expect(queryByText(debate.positions[1].name)).toBeInTheDocument(); - - const onSubmit = getByTestId("submit-button"); - expect(onSubmit).toBeInTheDocument(); - await act(async () => { - await userEvent.click(onSubmit); - }); - }); - it("should display error if the validation rules are not met", async () => { const targetContent = { root: { @@ -388,7 +331,6 @@ describe("ArgumentInput", () => { groupId={debate.id} groupName={debate.name} positions={debate.positions} - disabledPositions={[]} disabled listId={"argumentList"} positionId={debate.positions[0].id} @@ -510,7 +452,6 @@ describe("ArgumentInput", () => { groupId={debate.id} groupName={debate.name} positions={debate.positions} - disabledPositions={[]} disabled listId={"argumentList"} positionId={debate.positions[0].id} @@ -548,6 +489,131 @@ describe("ArgumentInput", () => { expect(callback).toHaveBeenCalled(); }); + it("should display an error toast when the API returns 429 (daily limit reached)", async () => { + const targetContent = { + root: { + children: [ + { + children: [ + { + detail: 0, + format: 1, + mode: "normal", + style: "", + text: "I write an argument", + type: "text", + version: 1, + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "paragraph", + version: 1, + }, + ], + direction: "ltr", + format: "", + indent: 0, + type: "root", + version: 1, + }, + }; + + const rejectingHttpClient = { + get: () => null, + post: () => { + return new Promise((_, reject) => { + reject({ + response: { + status: 429, + data: { success: false, error: {} }, + }, + }); + }); + }, + patch: () => null, + delete: () => new Promise((resolve) => resolve({ data: {} })), + }; + const rejectingData = dataProvider( + rejectingHttpClient, + "https://mock.example.api", + ); + + const AddContentComponent = () => { + const { setInputRichContent } = useInput(); + + const setContent = (event) => { + setInputRichContent(targetContent); + }; + + return ( + <> +
Click to set content
+ + ); + }; + + const { getByTestId, queryByText } = render( + + + + + + + + + + + + + + + + + + + + + + , + ); + + const input = getByTestId("argument-input"); + await act(async () => { + await userEvent.click(input); + }); + + const setContentButton = screen.getByText("Click to set content"); + await act(async () => { + await userEvent.click(setContentButton); + }); + + const onSubmit = getByTestId("submit-button"); + await act(async () => { + await userEvent.click(onSubmit); + }); + + expect( + queryByText( + "You have reached your daily contribution limit for this debate.", + ), + ).toBeInTheDocument(); + }); it("should focus editor when autoFocus is true", async () => { const { getByRole } = render( @@ -567,7 +633,6 @@ describe("ArgumentInput", () => { groupId={debate.id} groupName={debate.name} positions={debate.positions} - disabledPositions={[]} listId={"argumentList"} positionId={debate.positions[0].id} hideSourceAction={true} @@ -614,7 +679,6 @@ describe("ArgumentInput", () => { groupId={debate.id} groupName={debate.name} positions={debate.positions} - disabledPositions={[]} listId={"argumentList"} positionId={debate.positions[0].id} hideSourceAction={true} @@ -660,7 +724,6 @@ describe("ArgumentInput", () => { groupId={debate.id} groupName={debate.name} positions={[]} - disabledPositions={[]} listId={"argumentList"} positionId={null} hideSourceAction={false} diff --git a/src/components/modal/side_modal/SideModal.jsx b/src/components/modal/side_modal/SideModal.jsx index f2ace9bd..f59f8d90 100644 --- a/src/components/modal/side_modal/SideModal.jsx +++ b/src/components/modal/side_modal/SideModal.jsx @@ -11,7 +11,6 @@ export const SideModal = ({ onChooseSide, title, positions, - disabledPositions, isNeutral = false, }) => { const { hideModal } = useModal(); @@ -24,17 +23,6 @@ export const SideModal = ({ return (
{title}
- {disabledPositions?.length > 0 && ( -
- -
- )}
{positions.slice(0, 2).map((position) => { return ( @@ -43,11 +31,6 @@ export const SideModal = ({ key={position.id} className={styles.modalAction} onClick={() => handleChoosePosition(position.id)} - disabled={ - disabledPositions && - disabledPositions.filter((pos) => pos.id === position.id) - .length > 0 - } > { useTranslatedContent( diff --git a/src/components/modal/side_modal/SideModal.stories.jsx b/src/components/modal/side_modal/SideModal.stories.jsx index 63a324bb..901871a3 100644 --- a/src/components/modal/side_modal/SideModal.stories.jsx +++ b/src/components/modal/side_modal/SideModal.stories.jsx @@ -26,8 +26,6 @@ const debatePositions = [ ]; export const SideModalExample = () => { - const disabledPositions = []; - const handleChooseSide = (positionId) => { console.log(`Selected position: ${positionId}`); }; @@ -40,7 +38,6 @@ export const SideModalExample = () => { modalTitle={"Choose your side"} title={debateName} positions={debatePositions} - disabledPositions={disabledPositions} onChooseSide={handleChooseSide} isNeutral={false} /> @@ -51,8 +48,6 @@ export const SideModalExample = () => { }; export const SideModalWithNeutralPosition = () => { - const disabledPositions = []; - const handleChooseSide = (positionId) => { console.log(`Selected position: ${positionId}`); }; @@ -65,7 +60,6 @@ export const SideModalWithNeutralPosition = () => { modalTitle={"Choose your side"} title={debateName} positions={debatePositions} - disabledPositions={disabledPositions} onChooseSide={handleChooseSide} isNeutral={true} /> @@ -74,28 +68,3 @@ export const SideModalWithNeutralPosition = () => {
); }; - -export const SideModalWithDisabledPositions = () => { - const disabledPositions = [{ id: 2, name: "Position B" }]; - - const handleChooseSide = (positionId) => { - console.log(`Selected position: ${positionId}`); - }; - - return ( -
- - - - - -
- ); -}; diff --git a/src/components/modal/side_modal/SideModal.test.jsx b/src/components/modal/side_modal/SideModal.test.jsx index c61cb156..bd50a39e 100644 --- a/src/components/modal/side_modal/SideModal.test.jsx +++ b/src/components/modal/side_modal/SideModal.test.jsx @@ -2,7 +2,6 @@ import { render, screen } from "@testing-library/react"; import React from "react"; import { SideModalExample, - SideModalWithDisabledPositions, SideModalWithNeutralPosition, } from "./SideModal.stories"; @@ -37,12 +36,4 @@ describe("SideModal", () => { ).toBeInTheDocument(); }); - it("should render with warning when disabled positions", async () => { - render(); - expect( - screen.getByText( - "You have already reached the argument limit (10) for position Position B. You can support the other position.", - ), - ).toBeInTheDocument(); - }); });