Skip to content

Commit

Permalink
✨ Show subject stats/summary (#279)
Browse files Browse the repository at this point in the history
* ✨ Show subject stats/summary

* ✨ Show persistent comment on repositories table

* ✨ Add clear filter button to filter panel dropdown

* ✨ Update version and fix undefined render

* ✨ Add sort by account stat

* ✨ Add filters for stats

* 🚨 Fix linter issues

* 🧹 CLeanup

* 💄 Fix up stat text
  • Loading branch information
foysalit authored Jan 22, 2025
1 parent af447f3 commit 475c934
Show file tree
Hide file tree
Showing 15 changed files with 746 additions and 130 deletions.
18 changes: 16 additions & 2 deletions app/actions/ModActionPanel/QuickAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,15 @@ function Form(
{/* This is only meant to be switched on in mobile/small screen view */}
{/* The parent component ensures to toggle this based on the screen size */}
{replaceFormWithEvents ? (
<ModEventList subject={subject} />
<>
<ModEventList
subject={subject}
stats={{
accountStats: subjectStatus?.accountStats,
recordsStats: subjectStatus?.recordsStats,
}}
/>
</>
) : (
<div className="px-1">
{profile && (
Expand Down Expand Up @@ -886,7 +894,13 @@ function Form(
</div>
{!replaceFormWithEvents && (
<div className="hidden sm:block sm:w-1/2 sm:pl-4">
<ModEventList subject={subject} />
<ModEventList
stats={{
accountStats: subjectStatus?.accountStats,
recordsStats: subjectStatus?.recordsStats,
}}
subject={subject}
/>
</div>
)}
</div>
Expand Down
26 changes: 25 additions & 1 deletion app/reports/page-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,14 @@ const getSortParams = (params: ReadonlyURLSearchParams) => {
sortDirection = 'desc'
}

if (!['lastReportedAt', 'lastReviewedAt'].includes(sortField ?? '')) {
if (
![
'lastReportedAt',
'lastReviewedAt',
'reportedRecordsCount',
'takendownRecordsCount',
].includes(sortField ?? '')
) {
sortField = 'lastReportedAt'
}

Expand Down Expand Up @@ -306,6 +313,9 @@ function useModerationQueueQuery() {
const queueName = params.get('queueName')
const subjectType = params.get('subjectType')
const collections = params.get('collections')
const minAccountSuspendCount = params.get('minAccountSuspendCount')
const minReportedRecordsCount = params.get('minReportedRecordsCount')
const minTakendownRecordsCount = params.get('minTakendownRecordsCount')
const { sortField, sortDirection } = getSortParams(params)
const { lastReviewedBy, subject, reporters, includeAllUserRecords } =
useFluentReportSearchParams()
Expand All @@ -330,6 +340,8 @@ function useModerationQueueQuery() {
onlyMuted,
subjectType,
collections,
minAccountSuspendCount,
minReportedRecordsCount,
},
],
queryFn: async ({ pageParam }) => {
Expand Down Expand Up @@ -382,6 +394,18 @@ function useModerationQueueQuery() {
queryParams.excludeTags = excludeTags.split(',')
}

if (minAccountSuspendCount) {
queryParams.minAccountSuspendCount = Number(minAccountSuspendCount)
}

if (minReportedRecordsCount) {
queryParams.minReportedRecordsCount = Number(minReportedRecordsCount)
}

if (minTakendownRecordsCount) {
queryParams.minTakendownRecordsCount = Number(minTakendownRecordsCount)
}

// For these fields, we only want to add them to the filter if the values are set, otherwise, defaults will kick in
Object.entries({
sortField,
Expand Down
1 change: 0 additions & 1 deletion components/common/buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ const buttonSpaceMap = {
}

export const ButtonGroup = ({
appearance,
size = 'sm',
items,
leftAligned = false,
Expand Down
27 changes: 26 additions & 1 deletion components/mod-event/EventList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import {
} from '@heroicons/react/24/solid'
import { EventFilterPanel } from './FilterPanel'
import { ConfirmationModal } from '@/common/modals/confirmation'
import { ToolsOzoneModerationDefs } from '@atproto/api'
import { SubjectSummary } from '@/subject/Summary'
import { MOD_EVENTS } from './constants'

const getConfirmWorkspaceTitle = (
showWorkspaceConfirmation: WorkspaceConfirmationOptions,
Expand Down Expand Up @@ -126,7 +129,14 @@ const Header = ({
}

export const ModEventList = (
props: { subject?: string; createdBy?: string } & ModEventListQueryOptions,
props: {
subject?: string
createdBy?: string
stats?: {
accountStats?: ToolsOzoneModerationDefs.AccountStats
recordsStats?: ToolsOzoneModerationDefs.RecordsStats
}
} & ModEventListQueryOptions,
) => {
const {
types,
Expand Down Expand Up @@ -184,6 +194,13 @@ export const ModEventList = (
},
]

if (hasFilter) {
eventActions.push({
text: 'Clear filters',
onClick: () => resetListFilters(),
})
}

if (!noEvents) {
eventActions.push(
{
Expand All @@ -203,6 +220,14 @@ export const ModEventList = (

return (
<div className="mr-1">
{!!props.stats && (
<SubjectSummary
onAccountTakedownClick={() => {
changeListFilter({ field: 'types', value: [MOD_EVENTS.TAKEDOWN] })
}}
stats={props.stats}
/>
)}
<div className="flex flex-row justify-between items-center">
{!isEntireHistoryView ? (
<Header
Expand Down
15 changes: 14 additions & 1 deletion components/mod-event/useModEventList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,11 @@ const eventListReducer = (state: EventListState, action: EventListAction) => {
}

export const useModEventList = (
props: { subject?: string; createdBy?: string } & ModEventListQueryOptions,
props: {
subject?: string
createdBy?: string
eventType?: string
} & ModEventListQueryOptions,
) => {
const [showWorkspaceConfirmation, setShowWorkspaceConfirmation] =
useState<WorkspaceConfirmationOptions>(null)
Expand Down Expand Up @@ -228,6 +232,15 @@ export const useModEventList = (
}
}, [props.createdBy])

useEffect(() => {
if (props.eventType) {
dispatch({
type: 'SET_FILTER',
payload: { field: 'types', value: [props.eventType] },
})
}
}, [props.eventType])

const results = useInfiniteQuery<{
events: ModEventViewWithDetails[]
cursor?: string
Expand Down
3 changes: 2 additions & 1 deletion components/reports/QueueFilter/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { getLanguageFlag } from 'components/tags/SubjectTag'
import { getCollectionName } from '../helpers/subject'
import { classNames } from '@/lib/util'
import { QueueFilterTags } from './Tag'
import { QueueFilterStats } from './Stats'

const buildTagFilterSummary = (tags: string[]) => {
const filtered = tags.filter(Boolean)
Expand Down Expand Up @@ -147,8 +148,8 @@ export const QueueFilterPanel = () => {
<div className="flex flex-row px-2 gap-6">
<QueueFilterSubjectType />
</div>

<QueueFilterTags />
<QueueFilterStats />
</div>
</Popover.Panel>
</Transition>
Expand Down
61 changes: 61 additions & 0 deletions components/reports/QueueFilter/Stats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { FormLabel, Input } from '@/common/forms'
import { useQueueFilter } from '../useQueueFilter'

export const QueueFilterStats = () => {
const {
queueFilters,
setMinAccountSuspendCount,
setMinReportedRecordsCount,
setMinTakendownRecordsCount,
} = useQueueFilter()

const handleInputChange =
(handler: (val?: number) => void) =>
(e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value
if (inputValue === '') {
handler(undefined)
} else if (/^\d*$/.test(inputValue)) {
// Allow only digits by filtering non-numeric characters
handler(Number(inputValue))
}
}
return (
<div className="flex flex-row gap-6">
<div className="px-2 mt-4">
<div className="flex flex-row gap-2">
<FormLabel label="Min. Suspension count" className="mb-2">
<Input
type="number"
className="block w-full"
id="minAccountSuspendCount"
name="minAccountSuspendCount"
value={queueFilters.minAccountSuspendCount || ''}
onChange={handleInputChange(setMinAccountSuspendCount)}
/>
</FormLabel>
<FormLabel label="Min. Reported records">
<Input
type="number"
className="block w-full"
id="minReportedRecordsCount"
name="minReportedRecordsCount"
value={queueFilters.minReportedRecordsCount || ''}
onChange={handleInputChange(setMinReportedRecordsCount)}
/>
</FormLabel>
</div>
<FormLabel label="Min. Takendown records">
<Input
type="number"
className="block w-full"
id="minTakendownRecordsCount"
name="minTakendownRecordsCount"
value={queueFilters.minTakendownRecordsCount || ''}
onChange={handleInputChange(setMinTakendownRecordsCount)}
/>
</FormLabel>
</div>
</div>
)
}
15 changes: 15 additions & 0 deletions components/reports/useQueueFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,18 @@ export const useQueueFilter = () => {
updateFilters({ tags: [] })
}

const setMinAccountSuspendCount = (minAccountSuspendCount?: number) => {
updateFilters({ minAccountSuspendCount })
}

const setMinReportedRecordsCount = (minReportedRecordsCount?: number) => {
updateFilters({ minReportedRecordsCount })
}

const setMinTakendownRecordsCount = (minTakendownRecordsCount?: number) => {
updateFilters({ minTakendownRecordsCount })
}

return {
queueFilters,
updateFilters,
Expand All @@ -132,5 +144,8 @@ export const useQueueFilter = () => {
toggleSubjectType,
clearSubjectType,
clearTags,
setMinAccountSuspendCount,
setMinReportedRecordsCount,
setMinTakendownRecordsCount,
}
}
5 changes: 5 additions & 0 deletions components/repositories/RepositoriesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ function RepoRow(props: { repo: Repo; showEmail: boolean }) {
/>
)}
</div>
{subjectStatus?.comment && (
<p className="text-xs dark:text-gray-300 text-gray-700 max-w-xs">
<b>Note:</b> {subjectStatus.comment}
</p>
)}
<dl className="font-normal lg:hidden">
<dt className="sr-only">Name</dt>
<dd className="mt-1 truncate text-gray-700 dark:text-gray-100">
Expand Down
Loading

0 comments on commit 475c934

Please sign in to comment.