-
Notifications
You must be signed in to change notification settings - Fork 50
feat(web): evidence moderation #1743
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,4 @@ | ||||||||||||||||||||||||||
| import React, { useCallback, useRef, useState } from "react"; | ||||||||||||||||||||||||||
| import React, { useCallback, useMemo, useRef, useState } from "react"; | ||||||||||||||||||||||||||
| import styled from "styled-components"; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| import { useParams } from "react-router-dom"; | ||||||||||||||||||||||||||
|
|
@@ -17,6 +17,8 @@ import EvidenceCard from "components/EvidenceCard"; | |||||||||||||||||||||||||
| import { SkeletonEvidenceCard } from "components/StyledSkeleton"; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| import EvidenceSearch from "./EvidenceSearch"; | ||||||||||||||||||||||||||
| import { Divider } from "components/Divider"; | ||||||||||||||||||||||||||
| import { spamEvidencesIds } from "src/consts"; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const Container = styled.div` | ||||||||||||||||||||||||||
| width: 100%; | ||||||||||||||||||||||||||
|
|
@@ -54,12 +56,19 @@ const ScrollButton = styled(Button)` | |||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| `; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const SpamLabel = styled.label` | ||||||||||||||||||||||||||
| color: ${({ theme }) => theme.primaryBlue}; | ||||||||||||||||||||||||||
| align-self: center; | ||||||||||||||||||||||||||
| cursor: pointer; | ||||||||||||||||||||||||||
| `; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const Evidence: React.FC = () => { | ||||||||||||||||||||||||||
| const { id } = useParams(); | ||||||||||||||||||||||||||
| const { data: disputeData } = useDisputeDetailsQuery(id); | ||||||||||||||||||||||||||
| const ref = useRef<HTMLDivElement>(null); | ||||||||||||||||||||||||||
| const [search, setSearch] = useState<string>(); | ||||||||||||||||||||||||||
| const [debouncedSearch, setDebouncedSearch] = useState<string>(); | ||||||||||||||||||||||||||
| const [showSpam, setShowSpam] = useState(false); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const { data } = useEvidences(disputeData?.dispute?.externalDisputeId?.toString(), debouncedSearch); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
@@ -74,12 +83,22 @@ const Evidence: React.FC = () => { | |||||||||||||||||||||||||
| latestEvidence.scrollIntoView({ behavior: "smooth" }); | ||||||||||||||||||||||||||
| }, [ref]); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| console.log({ data }); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const evidences = useMemo(() => { | ||||||||||||||||||||||||||
| if (!data?.evidences) return; | ||||||||||||||||||||||||||
| const spamEvidences = data.evidences.filter((evidence) => isSpam(evidence.id)); | ||||||||||||||||||||||||||
| const realEvidences = data.evidences.filter((evidence) => !isSpam(evidence.id)); | ||||||||||||||||||||||||||
| return { realEvidences, spamEvidences }; | ||||||||||||||||||||||||||
| }, [data]); | ||||||||||||||||||||||||||
| console.log({ evidences }); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||
| <Container ref={ref}> | ||||||||||||||||||||||||||
| <EvidenceSearch {...{ search, setSearch, evidenceGroup: disputeData?.dispute?.externalDisputeId }} /> | ||||||||||||||||||||||||||
| <ScrollButton small Icon={DownArrow} text="Scroll to latest" onClick={scrollToLatest} /> | ||||||||||||||||||||||||||
| {data ? ( | ||||||||||||||||||||||||||
| data.evidences.map(({ evidence, sender, timestamp, name, description, fileURI, evidenceIndex }) => ( | ||||||||||||||||||||||||||
| {evidences?.realEvidences ? ( | ||||||||||||||||||||||||||
| evidences?.realEvidences.map(({ evidence, sender, timestamp, name, description, fileURI, evidenceIndex }) => ( | ||||||||||||||||||||||||||
| <EvidenceCard | ||||||||||||||||||||||||||
| key={timestamp} | ||||||||||||||||||||||||||
| index={parseInt(evidenceIndex)} | ||||||||||||||||||||||||||
|
|
@@ -90,9 +109,36 @@ const Evidence: React.FC = () => { | |||||||||||||||||||||||||
| ) : ( | ||||||||||||||||||||||||||
| <SkeletonEvidenceCard /> | ||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||
| {evidences?.spamEvidences.length !== 0 ? ( | ||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||
| <Divider /> | ||||||||||||||||||||||||||
| {showSpam ? ( | ||||||||||||||||||||||||||
| evidences?.spamEvidences.map( | ||||||||||||||||||||||||||
| ({ evidence, sender, timestamp, name, description, fileURI, evidenceIndex }) => ( | ||||||||||||||||||||||||||
| <EvidenceCard | ||||||||||||||||||||||||||
| key={timestamp} | ||||||||||||||||||||||||||
| index={parseInt(evidenceIndex)} | ||||||||||||||||||||||||||
| sender={sender?.id} | ||||||||||||||||||||||||||
| {...{ evidence, timestamp, name, description, fileURI }} | ||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| ) : ( | ||||||||||||||||||||||||||
| <SpamLabel onClick={() => setShowSpam(true)}>Show likely spam</SpamLabel> | ||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||
| ) : null} | ||||||||||||||||||||||||||
| {data && data.evidences.length === 0 ? <StyledLabel>There is no evidence submitted yet</StyledLabel> : null} | ||||||||||||||||||||||||||
| </Container> | ||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const isSpam = (id: string) => { | ||||||||||||||||||||||||||
| for (const spamId of spamEvidencesIds) { | ||||||||||||||||||||||||||
| if (id == spamId) return true; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
| const isSpam = (id: string) => { | |
| for (const spamId of spamEvidencesIds) { | |
| if (id == spamId) return true; | |
| } | |
| return false; | |
| }; | |
| const spamIdsSet = new Set(spamEvidencesIds); | |
| const isSpam = (id: string) => { | |
| return spamIdsSet.has(id); | |
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Parsing logic needs improvement for case-evidence pairs
The current implementation in
web/src/consts/index.tsonly splits by comma, but the format"0-2,3-1"requires parsing both the comma-separated values and the hyphen-separated case-evidence pairs. The code inEvidence/index.tsxcompares the full string without parsing the pairs properly.web/src/consts/index.ts: Add proper parsing to split both by comma and hyphen to extract case and evidence IDsweb/src/pages/Cases/CaseDetails/Evidence/index.tsx: Update comparison logic to match against the correct case-evidence pair structure🔗 Analysis chain
Verify the parsing logic for the evidence IDs format
The format "0-2,3-1" appears to represent case-evidence ID pairs. Ensure robust parsing in the consuming code.
Consider using a more explicit JSON format for better maintainability:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 203
Script:
Length of output: 1065