- {(role === Roles.Admin || role === Roles.SuperAdmin) && (
+ {isAdmin(role) && (
<>
{review?.isPublished ? (
{
)}
{(isClaimTypeAndNotSmallScreen ||
isSourceOrVerificationRequest) && (
-
- )}
+
+ )}
{enableViewReportPreview ? (
{
const { t } = useTranslation();
@@ -31,7 +32,7 @@ const ReviewAlert = ({ isHidden, isPublished, hideDescription }) => {
reviewNotStartedSelector
);
const reviewData = useSelector(machineService, reviewDataSelector);
- const userIsAdmin = role === Roles.Admin || role === Roles.SuperAdmin;
+ const userIsAdmin = isAdmin(role);
const isCrossChecking = useSelector(machineService, crossCheckingSelector);
const isAddCommentCrossChecking = useSelector(
machineService,
diff --git a/src/components/ClaimReview/form/DynamicReviewTaskForm.tsx b/src/components/ClaimReview/form/DynamicReviewTaskForm.tsx
index 121fe8226..54e2067f8 100644
--- a/src/components/ClaimReview/form/DynamicReviewTaskForm.tsx
+++ b/src/components/ClaimReview/form/DynamicReviewTaskForm.tsx
@@ -29,6 +29,7 @@ import WarningModal from "../../Modal/WarningModal";
import { currentNameSpace } from "../../../atoms/namespace";
import { CommentEnum, Roles } from "../../../types/enums";
import useAutoSaveDraft from "./hooks/useAutoSaveDraft";
+import { isAdmin } from "../../../utils/GetUserPermission";
const DynamicReviewTaskForm = ({ data_hash, personality, target }) => {
const {
@@ -123,9 +124,9 @@ const DynamicReviewTaskForm = ({ data_hash, personality, target }) => {
const isValidReviewer =
event === ReviewTaskEvents.sendToCrossChecking
? !data.crossCheckerId ||
- !reviewData.usersId.includes(data.crossCheckerId)
+ !reviewData.usersId.includes(data.crossCheckerId)
: !data.reviewerId ||
- !reviewData.usersId.includes(data.reviewerId);
+ !reviewData.usersId.includes(data.reviewerId);
setReviewerError(!isValidReviewer);
return isValidReviewer;
@@ -202,7 +203,7 @@ const DynamicReviewTaskForm = ({ data_hash, personality, target }) => {
const userIsReviewer = reviewData.reviewerId === userId;
const userIsCrossChecker = reviewData.crossCheckerId === userId;
const userIsAssignee = reviewData.usersId.includes(userId);
- const userIsAdmin = role === Roles.Admin || role === Roles.SuperAdmin;
+ const userIsAdmin = isAdmin(role);
if (
isReported &&
diff --git a/src/components/Debate/DebateHeader.tsx b/src/components/Debate/DebateHeader.tsx
index 87ddd4d7e..8ce9e3707 100644
--- a/src/components/Debate/DebateHeader.tsx
+++ b/src/components/Debate/DebateHeader.tsx
@@ -12,7 +12,7 @@ import { NameSpaceEnum } from "../../types/Namespace";
import { currentNameSpace } from "../../atoms/namespace";
import AletheiaButton, { ButtonType } from "../Button";
import { EditOutlined } from "@mui/icons-material";
-import { Roles } from "../../types/enums";
+import { isAdmin } from "../../utils/GetUserPermission";
const DebateHeader = ({ claim, title, personalities, userRole }) => {
const [personalitiesArray, setPersonalitiesArray] = useState(personalities);
@@ -49,7 +49,7 @@ const DebateHeader = ({ claim, title, personalities, userRole }) => {
style={{
paddingTop: "32px",
backgroundColor: colors.lightNeutral,
- justifyContent:"center"
+ justifyContent: "center"
}}
>
{
{title}
- {userRole === Roles.Admin && claim?.claimId ? (
+ {isAdmin(userRole) && claim?.claimId ? (
{
marginRight: vw?.lg && vw?.md && vw?.sm ? 0 : 160,
}}
>
- {t("debates:openEditDebateMode")}
+ {t("debates:openEditDebateMode")}
) : null}
{
setOpen(true)}
- data-cy={props}
+ data-cy={props.dataCy}
{...props}
/>}
PopperProps={{ placement: 'bottom-start', }}
diff --git a/src/components/Form/DynamicForm.tsx b/src/components/Form/DynamicForm.tsx
index 55de5a8a6..9a84795b3 100644
--- a/src/components/Form/DynamicForm.tsx
+++ b/src/components/Form/DynamicForm.tsx
@@ -75,7 +75,11 @@ const DynamicForm = ({
)}
/>
{errors[fieldName] && (
-
+
{t(errors[fieldName].message)}
)}
diff --git a/src/components/Form/DynamicInput.tsx b/src/components/Form/DynamicInput.tsx
index b8bdd5e2b..9596e57b4 100644
--- a/src/components/Form/DynamicInput.tsx
+++ b/src/components/Form/DynamicInput.tsx
@@ -92,10 +92,11 @@ const DynamicInput = (props: DynamicInputProps) => {
case "sourceList":
return (
props.onChange(value)}
disabled={props.disabled}
placeholder={props.placeholder}
+ dataCy={props["data-cy"]}
/>
);
case "select":
@@ -114,6 +115,7 @@ const DynamicInput = (props: DynamicInputProps) => {
onChange={(value) => props.onChange(value)}
placeholder={t(props.placeholder)}
isDisabled={props.disabled}
+ dataCy={props["data-cy"]}
/>
);
case "selectImpactArea":
@@ -123,6 +125,7 @@ const DynamicInput = (props: DynamicInputProps) => {
onChange={(value) => props.onChange(value)}
placeholder={t(props.placeholder)}
isDisabled={props.disabled}
+ dataCy={props["data-cy"]}
/>
);
case "imageUpload":
@@ -168,7 +171,7 @@ const DynamicInput = (props: DynamicInputProps) => {
defaultValue={props.defaultValue}
placeholder={t(props.placeholder)}
onChange={(value) => props.onChange(value)}
- data-cy={"testSelectDate"}
+ data-cy="testSelectDate"
disabledDate={props.disabledDate}
disabled={props.disabled}
style={{ backgroundColor: props.disabled ? colors.lightNeutral : colors.white }}
diff --git a/src/components/SentenceReport/SentenceReportPreviewView.tsx b/src/components/SentenceReport/SentenceReportPreviewView.tsx
index 78a30a73e..d31b851e0 100644
--- a/src/components/SentenceReport/SentenceReportPreviewView.tsx
+++ b/src/components/SentenceReport/SentenceReportPreviewView.tsx
@@ -21,6 +21,7 @@ import SentenceReportPreview from "./SentenceReportPreview";
import { useAppSelector } from "../../store/store";
import ClaimReviewHeader from "../ClaimReview/ClaimReviewHeader";
import { Content } from "../../types/Content";
+import { isAdmin } from "../../utils/GetUserPermission";
interface ISentenceReportViewV1Props {
context: any;
@@ -73,7 +74,7 @@ const SentenceReportPreviewView = ({
const isPublished =
useSelector(machineService, publishedSelector) ||
publishedReview?.review;
- const userIsAdmin = role === Roles.Admin || role === Roles.SuperAdmin;
+ const userIsAdmin = isAdmin(role);
const userIsCrossChecker = context.crossCheckerId === userId;
const userIsAssignee = context.usersId.includes(userId);
diff --git a/src/components/SentenceReport/SentenceReportView.tsx b/src/components/SentenceReport/SentenceReportView.tsx
index b4361f6c0..0cd90c943 100644
--- a/src/components/SentenceReport/SentenceReportView.tsx
+++ b/src/components/SentenceReport/SentenceReportView.tsx
@@ -3,7 +3,6 @@ import { Grid } from "@mui/material";
import React, { useContext } from "react";
import { ReviewTaskMachineContext } from "../../machines/reviewTask/ReviewTaskMachineProvider";
-import { Roles } from "../../types/enums";
import {
reviewingSelector,
publishedSelector,
@@ -18,6 +17,7 @@ import { useAtom } from "jotai";
import { currentUserId, currentUserRole } from "../../atoms/currentUser";
import SentenceReportComments from "./SentenceReportComments";
import { ReviewTaskTypeEnum } from "../../../server/types/enums";
+import { isAdmin } from "../../utils/GetUserPermission";
const SentenceReportView = ({
context,
@@ -44,7 +44,7 @@ const SentenceReportView = ({
const isPublished =
useSelector(machineService, publishedSelector) ||
publishedReview?.review;
- const userIsAdmin = role === Roles.Admin || role === Roles.SuperAdmin;
+ const userIsAdmin = isAdmin(role);
const canShowClassificationAndCrossChecking =
((isCrossChecking || isAddCommentCrossChecking) &&
diff --git a/src/components/SharedFormFooter.tsx b/src/components/SharedFormFooter.tsx
index 98d51a517..226986fde 100644
--- a/src/components/SharedFormFooter.tsx
+++ b/src/components/SharedFormFooter.tsx
@@ -11,7 +11,8 @@ interface ISharedFormFooter {
isLoading: boolean;
setRecaptchaString: Dispatch>;
hasCaptcha: boolean;
- hasCancelButton?: boolean;
+ isDrawerOpen?: boolean;
+ onClose?: () => void;
extraButton?: React.ReactNode;
}
@@ -19,7 +20,8 @@ const SharedFormFooter = ({
isLoading,
setRecaptchaString,
hasCaptcha,
- hasCancelButton = true,
+ isDrawerOpen,
+ onClose,
extraButton
}: ISharedFormFooter) => {
const recaptchaRef = useRef(null);
@@ -35,15 +37,16 @@ const SharedFormFooter = ({
justifyContent: "space-evenly",
}}
>
- {hasCancelButton ?
- router.back()}
- >
- {t("claimForm:cancelButton")}
-
- : extraButton
- }
+ isDrawerOpen ? onClose() : router.back()}
+ data-cy="testCancelButton"
+ >
+ {t("claimForm:cancelButton")}
+
+
+ {extraButton}
+
= ({ icon, label, label_value, style }) => {
+export const MetaChip: React.FC = ({ icon, label, label_value, style, dataCy }) => {
const { t } = useTranslation();
return (
= ({ icon, label, label_value, st
label={label_value || t("claimForm:noAnswer")}
style={style}
size="small"
+ data-cy={dataCy}
/>
);
-};
\ No newline at end of file
+};
diff --git a/src/components/VerificationRequest/RequestDates.tsx b/src/components/VerificationRequest/RequestDates.tsx
index c8b808838..d35a92bc7 100644
--- a/src/components/VerificationRequest/RequestDates.tsx
+++ b/src/components/VerificationRequest/RequestDates.tsx
@@ -6,18 +6,21 @@ interface RequestDatesProps {
icon?: React.ReactNode;
label: string;
value: string;
+ dataCy?: string;
}
-export const RequestDates: React.FC = ({ icon, label, value }) => {
+export const RequestDates: React.FC = ({ icon, label, value, dataCy }) => {
const publicationDate = new Date(value);
const isValidDate = !Number.isNaN(publicationDate.getTime());
return (
-
+
{icon}
{label}
@@ -25,4 +28,4 @@ export const RequestDates: React.FC = ({ icon, label, value }
);
-};
\ No newline at end of file
+};
diff --git a/src/components/VerificationRequest/SourceListVerificationRequest.tsx b/src/components/VerificationRequest/SourceListVerificationRequest.tsx
index d27e1a31f..1f6a93914 100644
--- a/src/components/VerificationRequest/SourceListVerificationRequest.tsx
+++ b/src/components/VerificationRequest/SourceListVerificationRequest.tsx
@@ -21,6 +21,7 @@ const SourceList: React.FC = ({ sources, t, id }) => {
{flatSources.map((source, index) => (
{
- {groupedRequests[status.key].map((request) => (
+ {groupedRequests[status.key].map((request, index) => (
{
diff --git a/src/components/VerificationRequest/VerificationRequestCard.tsx b/src/components/VerificationRequest/VerificationRequestCard.tsx
index 833a6f9bf..f5b7d3bbd 100644
--- a/src/components/VerificationRequest/VerificationRequestCard.tsx
+++ b/src/components/VerificationRequest/VerificationRequestCard.tsx
@@ -68,6 +68,7 @@ const VerificationRequestCard = ({
label_value: t(
`claimForm:${verificationRequest.reportType || "undefined"}`
),
+ dataCy: "testVerificationRequestReportType",
style: { backgroundColor: colors.secondary, color: colors.white },
},
{
@@ -79,6 +80,7 @@ const VerificationRequestCard = ({
`verificationRequest:${verificationRequest.sourceChannel}`,
{ defaultValue: verificationRequest.sourceChannel },
),
+ dataCy: "testVerificationRequestSourceChannel",
style: { backgroundColor: colors.primary, color: colors.white },
},
{
@@ -86,6 +88,7 @@ const VerificationRequestCard = ({
key: `${verificationRequest._id}|impactArea`,
label: t("verificationRequest:tagImpactArea"),
label_value: verificationRequest.impactArea?.name,
+ dataCy: "testVerificationRequestImpactArea",
style: {
backgroundColor: colors.neutralSecondary,
color: colors.white,
@@ -96,6 +99,7 @@ const VerificationRequestCard = ({
key: `${verificationRequest._id}|severity`,
label: t("verificationRequest:tagSeverity"),
label_value: getSeverityLabel(verificationRequest.severity, t),
+ dataCy: "testVerificationRequestSeverity",
style: {
backgroundColor: getSeverityColor(verificationRequest.severity),
color: colors.white,
@@ -132,6 +136,7 @@ const VerificationRequestCard = ({
{verificationRequest.publicationDate && (
}
label={t("verificationRequest:tagPublicationDate")}
value={verificationRequest.publicationDate}
@@ -162,6 +168,7 @@ const VerificationRequestCard = ({
{verificationRequest.date && (
}
label={t("verificationRequest:tagDate")}
value={verificationRequest.date}
@@ -173,6 +180,7 @@ const VerificationRequestCard = ({
)}
@@ -188,7 +196,7 @@ const VerificationRequestCard = ({
{metaChipData.map(
- ({ icon, key, label, label_value, style }) => (
+ ({ icon, key, label, label_value, style, dataCy }) => (
)
diff --git a/src/components/VerificationRequest/VerificationRequestContent.tsx b/src/components/VerificationRequest/VerificationRequestContent.tsx
index 09239789f..ab37969a9 100644
--- a/src/components/VerificationRequest/VerificationRequestContent.tsx
+++ b/src/components/VerificationRequest/VerificationRequestContent.tsx
@@ -4,15 +4,16 @@ import { Box, Typography } from "@mui/material";
interface VerificationRequestContentProps {
label: string;
value: React.ReactNode;
+ dataCy?: string;
}
-export const VerificationRequestContent: React.FC = ({ label, value }) => {
+export const VerificationRequestContent: React.FC = ({ label, value, dataCy }) => {
return (
-
+
{label}
@@ -20,4 +21,4 @@ export const VerificationRequestContent: React.FC
);
-};
\ No newline at end of file
+};
diff --git a/src/components/VerificationRequest/VerificationRequestDetailDrawer.tsx b/src/components/VerificationRequest/VerificationRequestDetailDrawer.tsx
index 0d81e09ca..d5d837c71 100644
--- a/src/components/VerificationRequest/VerificationRequestDetailDrawer.tsx
+++ b/src/components/VerificationRequest/VerificationRequestDetailDrawer.tsx
@@ -24,7 +24,7 @@ import {
ReviewTaskEvents,
ReviewTaskTypeEnum,
} from "../../machines/reviewTask/enums";
-import { Roles, VerificationRequestStatus } from "../../types/enums";
+import { VerificationRequestStatus } from "../../types/enums";
import { currentUserRole } from "../../atoms/currentUser";
import { useAppSelector } from "../../store/store";
import colors from "../../styles/colors";
@@ -47,6 +47,7 @@ import {
getSeverityColor,
getSeverityLabel,
} from "../../helpers/verificationRequestCardHelper";
+import { isStaff } from "../../utils/GetUserPermission";
interface VerificationRequestDetailDrawerProps {
verificationRequest: any;
@@ -83,11 +84,7 @@ const VerificationRequestDetailDrawer: React.FC {
setCurrentRequest(verificationRequest);
@@ -282,6 +279,7 @@ const VerificationRequestDetailDrawer: React.FC
- {role == Roles.Admin && (
+ {isAdmin(role) && (
setOpenEditDrawer(true)} />
@@ -64,7 +65,7 @@ const VerificationRequestMainContent = ({
{!vw.xs &&
- role !== Roles.Regular &&
+ isStaff(role) &&
verificationRequestGroup?.length > 0 && (
{
const {
handleSubmit,
@@ -40,6 +42,8 @@ const DynamicVerificationRequestForm = ({
isLoading={isLoading}
setRecaptchaString={setRecaptchaString}
hasCaptcha={hasCaptcha}
+ isDrawerOpen={isDrawerOpen}
+ onClose={onClose}
/>
);
diff --git a/src/components/VerificationRequest/verificationRequestForms/EditVerificationRequestDrawer.tsx b/src/components/VerificationRequest/verificationRequestForms/EditVerificationRequestDrawer.tsx
index 70218611b..a66b3dcfb 100644
--- a/src/components/VerificationRequest/verificationRequestForms/EditVerificationRequestDrawer.tsx
+++ b/src/components/VerificationRequest/verificationRequestForms/EditVerificationRequestDrawer.tsx
@@ -16,12 +16,18 @@ const EditVerificationRequestDrawer = ({
const [recaptchaString, setRecaptchaString] = useState("");
const hasCaptcha = !!recaptchaString;
const [isLoading, setIsLoading] = useState(false);
+ const sourceMapped = verificationRequest.source?.map(source => source.href);
+
+ const updatedVerificationRequest = {
+ ...verificationRequest,
+ source: sourceMapped?.length > 0 ? sourceMapped : undefined
+ }
const onSubmit = async (data) => {
try {
const updateData = {
publicationDate: data.publicationDate,
- source: data.source.map(url => ({ href: url })),
+ source: data.source?.map(url => ({ href: url })),
};
const response = await verificationRequestApi.updateVerificationRequest(
@@ -50,12 +56,14 @@ const EditVerificationRequestDrawer = ({
diff --git a/src/components/VerificationRequest/verificationRequestForms/formInputs/ImpactAreaSelect.tsx b/src/components/VerificationRequest/verificationRequestForms/formInputs/ImpactAreaSelect.tsx
index 7fe5a3d71..cfd5a2a07 100644
--- a/src/components/VerificationRequest/verificationRequestForms/formInputs/ImpactAreaSelect.tsx
+++ b/src/components/VerificationRequest/verificationRequestForms/formInputs/ImpactAreaSelect.tsx
@@ -7,8 +7,9 @@ const ImpactAreaSelect = ({
onChange,
placeholder,
isDisabled,
+ dataCy,
}: IImpactAreaSelect) => {
- const [value, setValue] = useState(null);
+ const [value, setValue] = useState(null);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
@@ -25,6 +26,7 @@ const ImpactAreaSelect = ({
setSelectedTags={setValue}
isMultiple={false}
isDisabled={isDisabled}
+ dataCy={dataCy}
/>
);
};
diff --git a/src/components/VerificationRequest/verificationRequestForms/formInputs/InputExtraSourcesList.tsx b/src/components/VerificationRequest/verificationRequestForms/formInputs/InputExtraSourcesList.tsx
index d26b2aaca..5e6e844cd 100644
--- a/src/components/VerificationRequest/verificationRequestForms/formInputs/InputExtraSourcesList.tsx
+++ b/src/components/VerificationRequest/verificationRequestForms/formInputs/InputExtraSourcesList.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from "react";
+import React, { useCallback, useMemo, useState } from "react";
import { Grid } from "@mui/material";
import AddIcon from "@mui/icons-material/Add";
import DeleteIcon from "@mui/icons-material/Delete";
@@ -7,13 +7,14 @@ import AletheiaButton, { ButtonType } from "../../../Button";
import AletheiaInput from "../../../AletheiaInput";
import { IInputExtraSourcesList } from "../../../../types/VerificationRequest";
import { SourceType } from "../../../../types/Source";
+import { debounce } from "lodash";
const formatSources = (sources: SourceType[]) => {
const sourceArray = Array.isArray(sources) ? sources : [];
if (sourceArray.length === 0) return [createEmptySource()];
return sourceArray.map((source) => ({
- id: source._id,
+ id: Math.random().toString(),
href: typeof source === "object" ? source.href : source || "",
isNewSource: !!(typeof source === "object" ? source.href : source),
}));
@@ -25,34 +26,43 @@ const createEmptySource = () => ({
isNewSource: false
});
-const InputExtraSourcesList = ({ sources, onChange, disabled, placeholder }: IInputExtraSourcesList) => {
+const InputExtraSourcesList = ({ defaultSources, onChange, disabled, placeholder, dataCy }: IInputExtraSourcesList) => {
const { t } = useTranslation();
- const [sourcesList, setSourcesList] = useState(() => formatSources(sources as SourceType[]));
+ const [sourcesList, setSourcesList] = useState(() => formatSources(defaultSources as SourceType[]));
- const handleSubmit = (hrefsList: typeof sourcesList) => {
- const updatedHrefs = [...new Set(hrefsList.map(source => source.href.trim()).filter(Boolean))];
- onChange(updatedHrefs);
- };
+ const handleListChange = useCallback((newSourcesList: typeof sourcesList) => {
+ const cleanedSources = [...new Set(newSourcesList.map(source => source.href.trim()).filter(Boolean))];
+ onChange(cleanedSources);
+ }, [onChange]);
+
+ const debouncedOnChange = useMemo(
+ () =>
+ debounce((SourcesList: typeof sourcesList) => {
+ handleListChange(SourcesList)
+ }, 800),
+ [handleListChange]
+ );
const updateSources = (id: string, newHref: string) => {
- const newHrefList = sourcesList.map(source => source.id === id ? { ...source, href: newHref } : source);
- setSourcesList(newHrefList);
- handleSubmit(newHrefList);
+ const newSourcesList = sourcesList.map(source => source.id === id ? { ...source, href: newHref } : source);
+ setSourcesList(newSourcesList);
+ debouncedOnChange(newSourcesList)
};
const addField = () => {
if (disabled) return;
- const newHrefList = [...sourcesList, createEmptySource()];
- setSourcesList(newHrefList);
- handleSubmit(newHrefList);
+ const newSourcesList = [...sourcesList, createEmptySource()];
+ setSourcesList(newSourcesList);
};
const removeField = (id: string, index: number) => {
if (disabled || index === 0) return;
- const newHrefList = sourcesList.filter((source) => source.id !== id);
+ const newSourcesList = sourcesList.filter((source) => source.id !== id);
+
+ setSourcesList(newSourcesList);
+ debouncedOnChange.cancel();
- setSourcesList(newHrefList);
- handleSubmit(newHrefList);
+ handleListChange(newSourcesList)
};
return (
@@ -72,12 +82,14 @@ const InputExtraSourcesList = ({ sources, onChange, disabled, placeholder }: IIn
disabled={disabled || (index === 0 && source.isNewSource)}
onChange={(newHref) => updateSources(source.id, newHref.target.value)}
placeholder={t(placeholder)}
+ data-cy={`${dataCy}Edit-${index}`}
white="true"
/>
{!disabled && index !== 0 && (
removeField(source.id, index)}
+ data-cy={`${dataCy}Remove-${index}`}
style={{ minWidth: "40px" }}
>
@@ -91,6 +103,7 @@ const InputExtraSourcesList = ({ sources, onChange, disabled, placeholder }: IIn
diff --git a/src/components/VerificationRequest/verificationRequestForms/formInputs/ReportTypeSelect.tsx b/src/components/VerificationRequest/verificationRequestForms/formInputs/ReportTypeSelect.tsx
index 6bccd5df8..30110105a 100644
--- a/src/components/VerificationRequest/verificationRequestForms/formInputs/ReportTypeSelect.tsx
+++ b/src/components/VerificationRequest/verificationRequestForms/formInputs/ReportTypeSelect.tsx
@@ -12,6 +12,7 @@ const ReportTypeSelect = ({
placeholder,
style = {},
isDisabled,
+ dataCy,
}: IReportTypeSelect) => {
const [value, setValue] = useState(defaultValue || "");
const { t } = useTranslation();
@@ -32,6 +33,7 @@ const ReportTypeSelect = ({
value={value}
style={style}
disabled={isDisabled}
+ data-cy={dataCy}
>