From 496bcecf20f3dfa084a755e64583a6f2dca6bfb8 Mon Sep 17 00:00:00 2001 From: bigint <69431456+bigint@users.noreply.github.com> Date: Wed, 14 Feb 2024 20:33:47 +0530 Subject: [PATCH] feat: update profile reports feed --- .../providers/hey/algorithms/heyReports.ts | 9 +++- .../hey/algorithms/heyTrustedReports.ts | 41 ------------------- .../{trusted => gardener}/removeReport.ts | 21 +++++----- .../{trusted => gardener}/reportDetails.ts | 19 ++++----- .../src/routes/{mod => gardener}/reports.ts | 10 +++-- apps/api/src/routes/trusted/publications.ts | 17 -------- apps/web/src/components/Mod/Actions.tsx | 24 ++++++----- ...tedReportDetails.tsx => ReportDetails.tsx} | 20 ++++----- apps/web/src/components/Mod/ReportsFeed.tsx | 14 +++---- .../src/components/Mod/TrustedReportsFeed.tsx | 10 +++-- .../Actions/GardenerActions/index.tsx | 25 ++++++----- 11 files changed, 83 insertions(+), 127 deletions(-) delete mode 100644 apps/api/src/lib/feeds/providers/hey/algorithms/heyTrustedReports.ts rename apps/api/src/routes/{trusted => gardener}/removeReport.ts (71%) rename apps/api/src/routes/{trusted => gardener}/reportDetails.ts (72%) rename apps/api/src/routes/{mod => gardener}/reports.ts (67%) delete mode 100644 apps/api/src/routes/trusted/publications.ts rename apps/web/src/components/Mod/{TrustedReportDetails.tsx => ReportDetails.tsx} (72%) diff --git a/apps/api/src/lib/feeds/providers/hey/algorithms/heyReports.ts b/apps/api/src/lib/feeds/providers/hey/algorithms/heyReports.ts index d6dd12b29602..3bc125a49f09 100644 --- a/apps/api/src/lib/feeds/providers/hey/algorithms/heyReports.ts +++ b/apps/api/src/lib/feeds/providers/hey/algorithms/heyReports.ts @@ -2,20 +2,25 @@ import { Errors } from '@hey/data/errors'; import logger from '@hey/lib/logger'; import createClickhouseClient from 'src/lib/createClickhouseClient'; -const heyReports = async (limit: number, offset: number): Promise => { +const heyReports = async ( + limit: number, + offset: number, + isTrusted = false +): Promise => { if (limit > 500) { throw new Error(Errors.Limit500); } try { const client = createClickhouseClient(); + const table = isTrusted ? 'trusted_reports' : 'reports'; const rows = await client.query({ format: 'JSONEachRow', query: ` SELECT publication_id AS id, count(*) as count - FROM reports + FROM ${table} WHERE resolved = 0 GROUP BY publication_id ORDER BY count DESC diff --git a/apps/api/src/lib/feeds/providers/hey/algorithms/heyTrustedReports.ts b/apps/api/src/lib/feeds/providers/hey/algorithms/heyTrustedReports.ts deleted file mode 100644 index 398cf258653f..000000000000 --- a/apps/api/src/lib/feeds/providers/hey/algorithms/heyTrustedReports.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Errors } from '@hey/data/errors'; -import logger from '@hey/lib/logger'; -import createClickhouseClient from 'src/lib/createClickhouseClient'; - -const heyTrustedReports = async ( - limit: number, - offset: number -): Promise => { - if (limit > 500) { - throw new Error(Errors.Limit500); - } - - try { - const client = createClickhouseClient(); - const rows = await client.query({ - format: 'JSONEachRow', - query: ` - SELECT - publication_id AS id, - count(*) as count - FROM trusted_reports - WHERE resolved = 0 - GROUP BY publication_id - ORDER BY count DESC - LIMIT ${limit} - OFFSET ${offset}; - ` - }); - - const result = await rows.json>(); - - const ids = result.map((r) => r.id); - logger.info(`[Hey] Trusted reports: ${ids.length} ids`); - - return ids; - } catch { - return []; - } -}; - -export default heyTrustedReports; diff --git a/apps/api/src/routes/trusted/removeReport.ts b/apps/api/src/routes/gardener/removeReport.ts similarity index 71% rename from apps/api/src/routes/trusted/removeReport.ts rename to apps/api/src/routes/gardener/removeReport.ts index 644dd93573c9..0df7e23bdf19 100644 --- a/apps/api/src/routes/trusted/removeReport.ts +++ b/apps/api/src/routes/gardener/removeReport.ts @@ -10,11 +10,13 @@ import { boolean, object, string } from 'zod'; type ExtensionRequest = { id: string; looksGood: boolean; + trusted: boolean; }; const validationSchema = object({ id: string(), - looksGood: boolean() + looksGood: boolean(), + trusted: boolean() }); export const post: Handler = async (req, res) => { @@ -34,25 +36,24 @@ export const post: Handler = async (req, res) => { return notAllowed(res); } - const { id, looksGood } = body as ExtensionRequest; + const { id, looksGood, trusted } = body as ExtensionRequest; + const table = trusted ? 'trusted_reports' : 'reports'; try { const client = createClickhouseClient(); if (looksGood) { await client.command({ - query: `DELETE FROM trusted_reports WHERE publication_id = '${id}';` + query: `DELETE FROM ${table} WHERE publication_id = '${id}';` }); - logger.info('Deleted report from trusted reports'); + + logger.info('Deleted report from reports'); } else { await client.command({ - query: ` - ALTER TABLE trusted_reports - UPDATE resolved = 1 - WHERE publication_id = '${id}'; - ` + query: `ALTER TABLE ${table} UPDATE resolved = 1 WHERE publication_id = '${id}';` }); - logger.info('Marked trusted report as resolved'); + + logger.info('Marked report as resolved'); } return res.status(200).json({ success: true }); diff --git a/apps/api/src/routes/trusted/reportDetails.ts b/apps/api/src/routes/gardener/reportDetails.ts similarity index 72% rename from apps/api/src/routes/trusted/reportDetails.ts rename to apps/api/src/routes/gardener/reportDetails.ts index 4064edb735d4..214f2882090a 100644 --- a/apps/api/src/routes/trusted/reportDetails.ts +++ b/apps/api/src/routes/gardener/reportDetails.ts @@ -6,34 +6,29 @@ import createClickhouseClient from 'src/lib/createClickhouseClient'; import { noBody } from 'src/lib/responses'; export const get: Handler = async (req, res) => { - const { id } = req.query; + const { id, trusted } = req.query; if (!id) { return noBody(res); } + const table = trusted === 'true' ? 'trusted_reports' : 'reports'; + try { const client = createClickhouseClient(); const rows = await client.query({ format: 'JSONEachRow', query: ` - SELECT - reason, - count(*) as count - FROM trusted_reports + SELECT reason, count(*) as count + FROM ${table} WHERE publication_id = '${id}' GROUP BY reason ORDER BY count DESC; ` }); - const result = await rows.json< - Array<{ - count: string; - reason: string; - }> - >(); - logger.info(`Trusted report details fetched for ${id}`); + const result = await rows.json>(); + logger.info(`Report details fetched for ${id}`); return res.status(200).json({ result: result.map((row) => ({ diff --git a/apps/api/src/routes/mod/reports.ts b/apps/api/src/routes/gardener/reports.ts similarity index 67% rename from apps/api/src/routes/mod/reports.ts rename to apps/api/src/routes/gardener/reports.ts index 8173cef470d4..ef9e63a85538 100644 --- a/apps/api/src/routes/mod/reports.ts +++ b/apps/api/src/routes/gardener/reports.ts @@ -6,11 +6,15 @@ import heyReports from 'src/lib/feeds/providers/hey/algorithms/heyReports'; export const get: Handler = async (req, res) => { const limit = (parseInt(req.query?.limit as string) || 50) as number; const offset = (parseInt(req.query?.offset as string) || 0) as number; + const trusted = req.query?.trusted as string; + + const isTrusted = trusted === 'true'; try { - return res - .status(200) - .json({ ids: await heyReports(limit, offset), success: true }); + return res.status(200).json({ + ids: await heyReports(limit, offset, isTrusted), + success: true + }); } catch (error) { return catchedError(res, error); } diff --git a/apps/api/src/routes/trusted/publications.ts b/apps/api/src/routes/trusted/publications.ts deleted file mode 100644 index 0691c3ea6612..000000000000 --- a/apps/api/src/routes/trusted/publications.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { Handler } from 'express'; - -import catchedError from 'src/lib/catchedError'; -import heyTrustedReports from 'src/lib/feeds/providers/hey/algorithms/heyTrustedReports'; - -export const get: Handler = async (req, res) => { - const limit = (parseInt(req.query?.limit as string) || 50) as number; - const offset = (parseInt(req.query?.offset as string) || 0) as number; - - try { - return res - .status(200) - .json({ ids: await heyTrustedReports(limit, offset), success: true }); - } catch (error) { - return catchedError(res, error); - } -}; diff --git a/apps/web/src/components/Mod/Actions.tsx b/apps/web/src/components/Mod/Actions.tsx index 8dfff49b777a..bb3f1b21bd36 100644 --- a/apps/web/src/components/Mod/Actions.tsx +++ b/apps/web/src/components/Mod/Actions.tsx @@ -1,23 +1,24 @@ import GardenerActions from '@components/Publication/Actions/GardenerActions'; import TrustedProfilesActions from '@components/Publication/Actions/TrustedProfilesActions'; +import { ModFeedType } from '@hey/data/enums'; import { type FC, useState } from 'react'; import { useFeatureFlagsStore } from 'src/store/persisted/useFeatureFlagsStore'; -import TrustedReportDetails from './TrustedReportDetails'; +import ReportDetails from './ReportDetails'; interface ActionsProps { - hideTrustedReport?: boolean; publicationId: string; + type?: ModFeedType.REPORTS | ModFeedType.TRUSTED_REPORTS; } -const Actions: FC = ({ - hideTrustedReport = false, - publicationId -}) => { +const Actions: FC = ({ publicationId, type }) => { const [expanded, setExpanded] = useState(true); const trusted = useFeatureFlagsStore((state) => state.trusted); const gardenerMode = useFeatureFlagsStore((state) => state.gardenerMode); + const isTrustedReport = type === ModFeedType.TRUSTED_REPORTS; + const isNormalReport = type === ModFeedType.REPORTS; + if (!expanded) { return null; } @@ -30,18 +31,21 @@ const Actions: FC = ({
Gardener actions
- {hideTrustedReport && ( - + {(isTrustedReport || isNormalReport) && ( + )} )} - {trusted && !hideTrustedReport && ( + {trusted && !isTrustedReport && !isNormalReport && ( <>
diff --git a/apps/web/src/components/Mod/TrustedReportDetails.tsx b/apps/web/src/components/Mod/ReportDetails.tsx similarity index 72% rename from apps/web/src/components/Mod/TrustedReportDetails.tsx rename to apps/web/src/components/Mod/ReportDetails.tsx index 9eb407964b88..d3143575db11 100644 --- a/apps/web/src/components/Mod/TrustedReportDetails.tsx +++ b/apps/web/src/components/Mod/ReportDetails.tsx @@ -4,23 +4,23 @@ import { HEY_API_URL } from '@hey/data/constants'; import { useQuery } from '@tanstack/react-query'; import axios from 'axios'; -interface TrustedReportDetailsProps { +interface ReportDetailsProps { + isTrustedReport: boolean; publicationId: string; } -const TrustedReportDetails: FC = ({ +const ReportDetails: FC = ({ + isTrustedReport, publicationId }) => { const fetchTrustedReportDetails = async (): Promise< - { - count: number; - reason: string; - }[] + { count: number; reason: string }[] > => { try { - const response = await axios.get(`${HEY_API_URL}/trusted/reportDetails`, { - params: { id: publicationId } - }); + const response = await axios.get( + `${HEY_API_URL}/gardener/reportDetails`, + { params: { id: publicationId, trusted: isTrustedReport } } + ); return response.data.result; } catch { @@ -51,4 +51,4 @@ const TrustedReportDetails: FC = ({ ); }; -export default TrustedReportDetails; +export default ReportDetails; diff --git a/apps/web/src/components/Mod/ReportsFeed.tsx b/apps/web/src/components/Mod/ReportsFeed.tsx index 4d7b7f98d807..e20a067dd5d7 100644 --- a/apps/web/src/components/Mod/ReportsFeed.tsx +++ b/apps/web/src/components/Mod/ReportsFeed.tsx @@ -5,6 +5,7 @@ import SinglePublication from '@components/Publication/SinglePublication'; import PublicationsShimmer from '@components/Shared/Shimmer/PublicationsShimmer'; import { SparklesIcon } from '@heroicons/react/24/outline'; import { HEY_API_URL } from '@hey/data/constants'; +import { ModFeedType } from '@hey/data/enums'; import { LimitType, usePublicationsQuery } from '@hey/lens'; import { Card, EmptyState, ErrorMessage } from '@hey/ui'; import { useQuery } from '@tanstack/react-query'; @@ -20,12 +21,9 @@ const ReportsFeed: FC = () => { const limit = LimitType.TwentyFive; const offset = displayedPublications.length; - const getTrustedReportFeed = async ( - limit: null | number, - offset: null | number - ) => { + const getReportFeed = async (limit: null | number, offset: null | number) => { try { - const response = await axios.get(`${HEY_API_URL}/mod/reports`, { + const response = await axios.get(`${HEY_API_URL}/gardener/reports`, { params: { limit, offset } }); @@ -40,8 +38,8 @@ const ReportsFeed: FC = () => { error: algoError, isLoading: algoLoading } = useQuery({ - queryFn: async () => await getTrustedReportFeed(25, offset), - queryKey: ['getTrustedReportFeed', 25, offset] + queryFn: async () => await getReportFeed(25, offset), + queryKey: ['getReportFeed', 25, offset] }); const request: PublicationsRequest = { @@ -100,7 +98,7 @@ const ReportsFeed: FC = () => { showActions={false} showThread={false} /> - + ))} diff --git a/apps/web/src/components/Mod/TrustedReportsFeed.tsx b/apps/web/src/components/Mod/TrustedReportsFeed.tsx index 8502b80bbede..0613c7485a59 100644 --- a/apps/web/src/components/Mod/TrustedReportsFeed.tsx +++ b/apps/web/src/components/Mod/TrustedReportsFeed.tsx @@ -5,6 +5,7 @@ import SinglePublication from '@components/Publication/SinglePublication'; import PublicationsShimmer from '@components/Shared/Shimmer/PublicationsShimmer'; import { SparklesIcon } from '@heroicons/react/24/outline'; import { HEY_API_URL } from '@hey/data/constants'; +import { ModFeedType } from '@hey/data/enums'; import { LimitType, usePublicationsQuery } from '@hey/lens'; import { Card, EmptyState, ErrorMessage } from '@hey/ui'; import { useQuery } from '@tanstack/react-query'; @@ -25,8 +26,8 @@ const TrustedReportsFeed: FC = () => { offset: null | number ) => { try { - const response = await axios.get(`${HEY_API_URL}/trusted/publications`, { - params: { limit, offset } + const response = await axios.get(`${HEY_API_URL}/gardener/reports`, { + params: { limit, offset, trusted: true } }); return response.data.success ? response.data.ids : []; @@ -100,7 +101,10 @@ const TrustedReportsFeed: FC = () => { showActions={false} showThread={false} /> - + ))} diff --git a/apps/web/src/components/Publication/Actions/GardenerActions/index.tsx b/apps/web/src/components/Publication/Actions/GardenerActions/index.tsx index aa74b3d5a0bb..ea1e2ac18918 100644 --- a/apps/web/src/components/Publication/Actions/GardenerActions/index.tsx +++ b/apps/web/src/components/Publication/Actions/GardenerActions/index.tsx @@ -7,6 +7,7 @@ import { HandThumbUpIcon } from '@heroicons/react/24/outline'; import { HEY_API_URL } from '@hey/data/constants'; +import { ModFeedType } from '@hey/data/enums'; import { GARDENER } from '@hey/data/tracking'; import { PublicationReportingSpamSubreason, @@ -22,38 +23,40 @@ import { toast } from 'react-hot-toast'; import { useGlobalAlertStateStore } from 'src/store/non-persisted/useGlobalAlertStateStore'; interface GardenerActionsProps { - ableToRemoveReport?: boolean; className?: string; publicationId: string; setExpanded?: (expanded: boolean) => void; + type?: ModFeedType.REPORTS | ModFeedType.TRUSTED_REPORTS; } const GardenerActions: FC = ({ - ableToRemoveReport = false, className = '', publicationId, - setExpanded = () => {} + setExpanded = () => {}, + type }) => { const setShowGardenerActionsAlert = useGlobalAlertStateStore( (state) => state.setShowGardenerActionsAlert ); const [createReport, { loading }] = useReportPublicationMutation(); + const ableToRemoveReport = + type === ModFeedType.TRUSTED_REPORTS || type === ModFeedType.REPORTS; - const removeTrustedReport = (id: string, looksGood: boolean) => { + const removeReport = (id: string, looksGood: boolean) => { const removeReport = async () => { return await axios.post( - `${HEY_API_URL}/trusted/removeReport`, - { id, looksGood }, + `${HEY_API_URL}/gardener/removeReport`, + { id, looksGood, trusted: type === ModFeedType.TRUSTED_REPORTS }, { headers: getAuthApiHeaders() } ); }; toast.promise(removeReport(), { - error: 'Error removing trusted reports', - loading: 'Removing trusted reports...', + error: 'Error removing report', + loading: 'Removing report...', success: () => { setExpanded(false); - return 'Trusted reports removed successfully'; + return 'Report removed successfully'; } }); }; @@ -77,7 +80,7 @@ const GardenerActions: FC = ({ }; if (ableToRemoveReport) { - removeTrustedReport(publicationId, false); + removeReport(publicationId, false); } return await createReport({ @@ -168,7 +171,7 @@ const GardenerActions: FC = ({ {ableToRemoveReport && (