Skip to content
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

feat(web): evidence moderation #1743

Merged
merged 2 commits into from
Nov 18, 2024
Merged

feat(web): evidence moderation #1743

merged 2 commits into from
Nov 18, 2024

Conversation

Harman-singh-waraich
Copy link
Contributor

@Harman-singh-waraich Harman-singh-waraich commented Nov 18, 2024

PR-Codex overview

This PR introduces functionality to handle and display spam evidences in the Evidence component, enhancing the user experience by allowing users to view or hide likely spam submissions.

Detailed summary

  • Added REACT_APP_SPAM_EVIDENCES_IDS environment variable to .env.devnet.public.
  • Introduced spamEvidencesIds constant in web/src/consts/index.ts.
  • Updated Evidence component to filter and display spam evidences.
  • Added a toggle feature to show/hide spam evidences with a SpamLabel.
  • Implemented isSpam function to check if an evidence ID is in the spam list.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features

    • Introduced a new environment variable for spam evidence IDs.
    • Added functionality to toggle the visibility of spam evidence in the Evidence component.
    • Implemented a clickable label for displaying spam evidence.
  • Enhancements

    • Improved state management and rendering logic for evidence handling in the Evidence component.
  • Refactor

    • Separated real and spam evidences for better clarity and organization.

Copy link
Contributor

coderabbitai bot commented Nov 18, 2024

Walkthrough

This pull request introduces several enhancements related to spam evidence management within the application. A new environment variable, REACT_APP_SPAM_EVIDENCES_IDS, is added to the .env.devnet.public file. This variable is utilized in the web/src/consts/index.ts file to create a new constant, spamEvidencesIds, which is an array of spam evidence IDs. Additionally, the Evidence component in web/src/pages/Cases/CaseDetails/Evidence/index.tsx is updated to include functionality for displaying spam evidence, allowing users to toggle its visibility.

Changes

File Change Summary
web/.env.devnet.public Added new environment variable: export REACT_APP_SPAM_EVIDENCES_IDS="0-2,3-1"
web/src/consts/index.ts Added new constant: export const spamEvidencesIds: string[] initialized from the environment variable
web/src/pages/Cases/CaseDetails/Evidence/index.tsx Updated Evidence component: added SpamLabel, showSpam state, isSpam function, and refactored evidence handling logic

Possibly related PRs

  • fix(web): submit-evidence-button-disable-condition #1722: The changes in this PR involve the SubmitEvidenceModal component, which is part of the same evidence handling functionality as the changes made in the main PR, specifically regarding the handling of spam evidence.
  • fix(web): error-handling-in-submit-evidence-modal #1724: This PR also modifies the SubmitEvidenceModal component, enhancing error handling during evidence submission, which is relevant to the overall functionality of managing evidence, including spam evidence as introduced in the main PR.

Suggested labels

Type: Enhancement :sparkles:, Package: Web

Suggested reviewers

  • alcercu

🐇 In the meadow where the spam does play,
A label prompts to show the way.
With toggles bright and evidence clear,
The rabbit hops without a fear.
New constants bloom, a code delight,
In our world, all feels just right! 🌼


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

netlify bot commented Nov 18, 2024

Deploy Preview for kleros-v2-testnet-devtools ready!

Name Link
🔨 Latest commit 519a555
🔍 Latest deploy log https://app.netlify.com/sites/kleros-v2-testnet-devtools/deploys/673a97f17e304e00089cbc5f
😎 Deploy Preview https://deploy-preview-1743--kleros-v2-testnet-devtools.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

netlify bot commented Nov 18, 2024

Deploy Preview for kleros-v2-university ready!

Name Link
🔨 Latest commit 519a555
🔍 Latest deploy log https://app.netlify.com/sites/kleros-v2-university/deploys/673a97f103cc1400085d1af2
😎 Deploy Preview https://deploy-preview-1743--kleros-v2-university.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

netlify bot commented Nov 18, 2024

Deploy Preview for kleros-v2-testnet ready!

Name Link
🔨 Latest commit 519a555
🔍 Latest deploy log https://app.netlify.com/sites/kleros-v2-testnet/deploys/673a97f1d6c7d70008d551e2
😎 Deploy Preview https://deploy-preview-1743--kleros-v2-testnet.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

netlify bot commented Nov 18, 2024

Deploy Preview for kleros-v2-neo ready!

Name Link
🔨 Latest commit 519a555
🔍 Latest deploy log https://app.netlify.com/sites/kleros-v2-neo/deploys/673a97f12dcd74000858a026
😎 Deploy Preview https://deploy-preview-1743--kleros-v2-neo.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (5)
web/.env.devnet.public (1)

10-10: Add documentation for the format

The variable's value format is not immediately clear and could benefit from documentation.

+# Format: comma-separated list of case-evidence pairs (e.g., "caseId-evidenceId,caseId-evidenceId")
 export REACT_APP_SPAM_EVIDENCES_IDS="0-2,3-1"
web/src/consts/index.ts (1)

46-46: Add documentation for the spam evidence ID format

Please add JSDoc comments to document:

  1. The expected format of the environment variable
  2. The structure of each spam evidence ID
  3. Example usage

Add this documentation above the constant:

+/**
+ * Array of spam evidence IDs parsed from REACT_APP_SPAM_EVIDENCES_IDS environment variable.
+ * 
+ * @example
+ * // Environment variable format: "groupId-evidenceId,groupId-evidenceId"
+ * REACT_APP_SPAM_EVIDENCES_IDS="0-2,3-1"
+ */
export const spamEvidencesIds: string[] = (import.meta.env.REACT_APP_SPAM_EVIDENCES_IDS ?? "").split(",");
web/src/pages/Cases/CaseDetails/Evidence/index.tsx (3)

59-63: Consider adding hover state for better UX

The spam label would benefit from a hover state to provide better visual feedback to users.

 const SpamLabel = styled.label`
   color: ${({ theme }) => theme.primaryBlue};
   align-self: center;
   cursor: pointer;
+  &:hover {
+    text-decoration: underline;
+  }
 `;

88-93: Optimize evidence filtering

The current implementation makes two passes over the data array. This can be optimized to use a single pass with reduce.

   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 };
+    return data.evidences.reduce(
+      (acc, evidence) => {
+        if (isSpam(evidence.id)) {
+          acc.spamEvidences.push(evidence);
+        } else {
+          acc.realEvidences.push(evidence);
+        }
+        return acc;
+      },
+      { realEvidences: [], spamEvidences: [] }
+    );
   }, [data]);

Line range hint 100-130: Refactor evidence rendering for better maintainability

The current implementation duplicates the EvidenceCard rendering logic. Consider extracting it into a reusable component.

+const EvidenceList = ({ evidences }) => (
+  evidences?.map(({ evidence, sender, timestamp, name, description, fileURI, evidenceIndex }) => (
+    <EvidenceCard
+      key={timestamp}
+      index={parseInt(evidenceIndex)}
+      sender={sender?.id}
+      {...{ evidence, timestamp, name, description, fileURI }}
+    />
+  ))
+);

 {evidences?.realEvidences ? (
-  evidences?.realEvidences.map(({ evidence, sender, timestamp, name, description, fileURI, evidenceIndex }) => (
-    <EvidenceCard
-      key={timestamp}
-      index={parseInt(evidenceIndex)}
-      sender={sender?.id}
-      {...{ evidence, timestamp, name, description, fileURI }}
-    />
-  ))
+  <EvidenceList evidences={evidences.realEvidences} />
 ) : (
   <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 }}
-          />
-        )
-      )
+      <EvidenceList evidences={evidences.spamEvidences} />
     ) : (
       <SpamLabel onClick={() => setShowSpam(true)}>Show likely spam</SpamLabel>
     )}
   </>
 ) : null}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 665a091 and 5d915e5.

📒 Files selected for processing (3)
  • web/.env.devnet.public (1 hunks)
  • web/src/consts/index.ts (1 hunks)
  • web/src/pages/Cases/CaseDetails/Evidence/index.tsx (5 hunks)
🔇 Additional comments (1)
web/src/consts/index.ts (1)

46-46: 🛠️ Refactor suggestion

Add validation and proper parsing for spam evidence IDs

The current implementation has potential issues:

  1. No validation of the environment variable format
  2. No trimming of whitespace
  3. The ID format (e.g., "0-2,3-1") needs parsing into a more usable structure

Consider this improved implementation:

-export const spamEvidencesIds: string[] = (import.meta.env.REACT_APP_SPAM_EVIDENCES_IDS ?? "").split(",");
+interface SpamEvidence {
+  groupId: number;
+  evidenceId: number;
+}
+
+export const spamEvidencesIds: SpamEvidence[] = (import.meta.env.REACT_APP_SPAM_EVIDENCES_IDS ?? "")
+  .split(",")
+  .filter(Boolean)
+  .map((id) => id.trim())
+  .map((id) => {
+    const [groupId, evidenceId] = id.split("-").map(Number);
+    if (isNaN(groupId) || isNaN(evidenceId)) {
+      throw new Error(`Invalid spam evidence ID format: ${id}`);
+    }
+    return { groupId, evidenceId };
+  });

Let's verify how this constant is used in the Evidence component:

@@ -7,5 +7,6 @@ export REACT_APP_GENESIS_BLOCK_ARBSEPOLIA=3084598
export REACT_APP_ATLAS_URI=http://localhost:3000
export REACT_APP_DEVTOOLS_URL=https://dev--kleros-v2-testnet-devtools.netlify.app
export NODE_OPTIONS='--max-old-space-size=7680'
export REACT_APP_SPAM_EVIDENCES_IDS="0-2,3-1"
Copy link
Contributor

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.ts only 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 in Evidence/index.tsx compares 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 IDs
  • web/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:

-export REACT_APP_SPAM_EVIDENCES_IDS="0-2,3-1"
+export REACT_APP_SPAM_EVIDENCES_IDS='[{"caseId":0,"evidenceId":2},{"caseId":3,"evidenceId":1}]'
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check how this environment variable is parsed and validate error handling
# Expected: Find parsing logic and error handling for the format "case-evidence,case-evidence"

# Search for direct environment variable usage
rg "REACT_APP_SPAM_EVIDENCES_IDS" -A 5

# Search for potential parsing logic
ast-grep --pattern 'split($$$)'

Length of output: 203


Script:

#!/bin/bash
# Let's check how these IDs are used in the codebase
rg "spamEvidencesIds" -A 5

# Also check for any validation or error handling around these IDs
ast-grep --pattern 'const spamEvidencesIds = $$$'

Length of output: 1065

@@ -74,12 +83,22 @@ const Evidence: React.FC = () => {
latestEvidence.scrollIntoView({ behavior: "smooth" });
}, [ref]);

console.log({ data });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove console.log statements

Console.log statements should be removed before pushing to production as they can impact performance and expose sensitive information.

-  console.log({ data });
-  console.log({ evidences });

Also applies to: 94-94

Comment on lines 136 to 142
const isSpam = (id: string) => {
for (const spamId of spamEvidencesIds) {
if (id == spamId) return true;
}

return false;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix equality check and optimize spam check performance

The current implementation has two issues:

  1. Uses loose equality (==) which could lead to unexpected behavior
  2. Iterates through array for each check when a Set would be more efficient
+const spamIdsSet = new Set(spamEvidencesIds);
+
 const isSpam = (id: string) => {
-  for (const spamId of spamEvidencesIds) {
-    if (id == spamId) return true;
-  }
-
-  return false;
+  return spamIdsSet.has(id);
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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);
};

Copy link

codeclimate bot commented Nov 18, 2024

Code Climate has analyzed commit 519a555 and detected 2 issues on this pull request.

Here's the issue category breakdown:

Category Count
Duplication 2

View more on Code Climate.

Copy link

sonarcloud bot commented Nov 18, 2024

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
web/src/pages/Cases/CaseDetails/Evidence/index.tsx (3)

71-71: Optimize the useMemo implementation.

The current implementation could be improved for better type safety and performance.

Consider applying these improvements:

-  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]);
+  const evidences = useMemo(() => {
+    if (!data?.evidences) return { realEvidences: [], spamEvidences: [] };
+    return {
+      spamEvidences: data.evidences.filter((evidence) => isSpam(evidence.id)),
+      realEvidences: data.evidences.filter((evidence) => !isSpam(evidence.id))
+    };
+  }, [data?.evidences]);

Changes:

  1. Explicit return type for the undefined case
  2. More specific dependency array
  3. Single pass through the data array

Also applies to: 86-91


Line range hint 97-127: Consider extracting the EvidenceCard rendering logic.

The EvidenceCard rendering logic is duplicated between real and spam evidences.

Consider extracting the common logic:

+ const renderEvidenceCard = useCallback(
+   ({ evidence, sender, timestamp, name, description, fileURI, evidenceIndex }) => (
+     <EvidenceCard
+       key={timestamp}
+       index={parseInt(evidenceIndex)}
+       sender={sender?.id}
+       {...{ evidence, timestamp, name, description, fileURI }}
+     />
+   ),
+   []
+ );

  {evidences?.realEvidences ? (
-   evidences?.realEvidences.map(({ evidence, sender, timestamp, name, description, fileURI, evidenceIndex }) => (
-     <EvidenceCard
-       key={timestamp}
-       index={parseInt(evidenceIndex)}
-       sender={sender?.id}
-       {...{ evidence, timestamp, name, description, fileURI }}
-     />
-   ))
+   evidences.realEvidences.map(renderEvidenceCard)
  ) : (
    <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 }}
-           />
-         )
-       )
+       evidences.spamEvidences.map(renderEvidenceCard)
      ) : (
        <SpamLabel onClick={() => setShowSpam(true)}>Show likely spam</SpamLabel>
      )}
    </>
  )}

Error handling needs to be implemented for evidence fetching

The component currently lacks error handling for the useEvidences hook. While there is a global QueryClientProvider, it doesn't provide specific error handling for query failures. The component should handle potential errors to prevent silent failures and provide feedback to users.

- const { data } = useEvidences(disputeData?.dispute?.externalDisputeId?.toString(), debouncedSearch);
+ const { data, error, isError } = useEvidences(disputeData?.dispute?.externalDisputeId?.toString(), debouncedSearch);

+ if (isError) {
+   return <div>Failed to load evidence: {error?.message}</div>;
+ }
🔗 Analysis chain

Line range hint 64-132: Verify error handling for evidence fetching.

The component should handle potential errors when fetching evidence data to prevent crashes and provide feedback to users.

Let's check if error boundaries exist in parent components:

Consider adding error handling:

  const { data } = useEvidences(disputeData?.dispute?.externalDisputeId?.toString(), debouncedSearch);
+ const { error } = useEvidences(disputeData?.dispute?.externalDisputeId?.toString(), debouncedSearch);
+ 
+ if (error) {
+   return <div>Error loading evidences: {error.message}</div>;
+ }
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for error boundary implementation in parent components

# Check for error boundary implementations
echo "Checking for error boundary implementations..."
rg -l "ErrorBoundary|componentDidCatch|getDerivedStateFromError" src/pages/Cases/

# Check for error handling in parent components
echo "Checking for error handling in parent components..."
ast-grep --pattern 'catch (error) { $$$  }' src/pages/Cases/

Length of output: 483


Script:

#!/bin/bash
# Let's try searching from the repository root with correct paths
echo "Checking for error boundary implementations..."
rg -l "ErrorBoundary|componentDidCatch|getDerivedStateFromError" web/src/pages/Cases/

echo "Checking for error handling in parent components..."
ast-grep --pattern 'catch (error) { $$$ }' web/src/pages/Cases/

# Also check for error handling in the Evidence component's query hook
echo "Checking error handling in useEvidences hook..."
rg "useEvidences" -A 5 web/src/

Length of output: 2132


Script:

#!/bin/bash
# Let's check the useQuery implementation and error handling
echo "Checking useQuery implementation..."
rg "useQuery" -A 10 web/src/hooks/queries/useEvidences.ts

# Let's also check if there's any global error handling setup
echo "Checking for global error handling..."
rg -l "QueryClientProvider|ErrorBoundary" web/src/

Length of output: 1211


Script:

#!/bin/bash
# Let's check the global error handling setup in these files
echo "Checking QueryClientProvider setup..."
cat web/src/context/QueryClientProvider.tsx

echo "Checking app.tsx error handling..."
cat web/src/app.tsx

Length of output: 4742


Script:

#!/bin/bash
# Let's check if there's error handling in SentryRoutes
echo "Checking SentryRoutes implementation..."
cat web/src/utils/sentry.tsx

# Also check if there's any error handling in the Cases component
echo "Checking Cases component..."
cat web/src/pages/Cases/index.tsx

Length of output: 1179

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5d915e5 and 519a555.

📒 Files selected for processing (1)
  • web/src/pages/Cases/CaseDetails/Evidence/index.tsx (5 hunks)
🔇 Additional comments (1)
web/src/pages/Cases/CaseDetails/Evidence/index.tsx (1)

1-1: LGTM: Import changes and styled component implementation.

The new imports and styled component implementation follow React and styled-components best practices.

Also applies to: 20-21, 59-63

@jaybuidl jaybuidl changed the title fix(web): evidence-sensor feat(web): evidence moderation Nov 18, 2024
@jaybuidl jaybuidl merged commit b03eb5a into dev Nov 18, 2024
28 of 29 checks passed
@jaybuidl jaybuidl deleted the fix/evidence-sensor branch November 18, 2024 01:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants