From c3c7c329f14cbba9ce0e84242d9b99121502ffbd Mon Sep 17 00:00:00 2001 From: Foysal Ahamed Date: Tue, 6 Feb 2024 19:40:40 +0100 Subject: [PATCH] :sparkles: Add filters for labels and report type --- app/actions/ModActionPanel/QuickAction.tsx | 1 - components/common/labels/Grid.tsx | 153 ++------------------- components/mod-event/EventList.tsx | 69 +++++++++- components/mod-event/useModEventList.tsx | 39 +++++- components/reports/ReportPanel.tsx | 11 +- components/reports/helpers/getType.ts | 12 ++ package.json | 2 +- yarn.lock | 93 ++++++++++++- 8 files changed, 216 insertions(+), 164 deletions(-) diff --git a/app/actions/ModActionPanel/QuickAction.tsx b/app/actions/ModActionPanel/QuickAction.tsx index 053bec2e..48e559bc 100644 --- a/app/actions/ModActionPanel/QuickAction.tsx +++ b/app/actions/ModActionPanel/QuickAction.tsx @@ -560,7 +560,6 @@ function Form( id="labels" name="labels" formId={FORM_ID} - subject={subject} defaultLabels={currentLabels.filter( (label) => !isSelfLabel(label), )} diff --git a/components/common/labels/Grid.tsx b/components/common/labels/Grid.tsx index d603dfd1..01715d19 100644 --- a/components/common/labels/Grid.tsx +++ b/components/common/labels/Grid.tsx @@ -1,163 +1,25 @@ -import { Fragment, useState, useEffect } from 'react' +import { useState } from 'react' import Select from 'react-tailwindcss-select' -import { Disclosure, Transition } from '@headlessui/react' -import { LabelChip, LabelListEmpty } from './List' import { labelOptions, displayLabel, groupLabelList, getLabelGroupInfo, - isSelfLabel, buildAllLabelOptions, - unFlagSelfLabel, } from './util' -import { classNames } from '@/lib/util' const EMPTY_ARR = [] type SelectProps = React.ComponentProps -// TODO: Probably redundant -export function LabelsGrid(props: LabelsProps) { - const { - id, - formId, - name, - className = '', - defaultLabels = EMPTY_ARR, - options = labelOptions, - disabled, - subject, - ...others - } = props - const allOptions = buildAllLabelOptions(defaultLabels, options) - const [current, setCurrent] = useState(defaultLabels) - - // update the current list when the current labels prop changes - // default labels are an array of strings so passing that as dependency to the useEffect hook will - // cause the current state to change everytime some other prop changes. the string conversion shields - // us from that. only caveat is that it won't work when the labels don't change just their order is changed - const defaultLabelsKey = defaultLabels.join('_') - useEffect(() => { - setCurrent(defaultLabels) - }, [defaultLabelsKey, subject]) - - const handleCheckboxChange = (opt: string) => { - // don't allow self labels to be changed - if (isSelfLabel(opt)) return - setCurrent((prev) => { - if (prev.includes(opt)) { - return prev.filter((item) => item !== opt) - } else { - return [...prev, opt] - } - }) - } - - const groupedLabelList = groupLabelList(allOptions) - // Sort by number of labels in each group so that the lists of labels take less vertical space in the UI - const sortedLabelList = Object.values(groupedLabelList).sort( - (a, b) => b.labels?.length - a.labels?.length, - ) - - return ( - - - {!current.length && (click to add)} - {current.map((label) => { - const labelGroup = getLabelGroupInfo(unFlagSelfLabel(label)) - return ( - - {displayLabel(label)} - - - ) - })} - - - -
- {sortedLabelList.map((group) => { - const groupTitle = group.strings.settings.en.name - return ( -
-

{groupTitle}

- {group.labels.map((opt, i) => { - const labelText = typeof opt === 'string' ? opt : opt.id - const cantChange = isSelfLabel(labelText) - return ( -
-
- handleCheckboxChange(labelText)} - className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-600" - onKeyDown={(e) => { - if (e.key === 'Enter') { - e.preventDefault() // make sure we don't submit the form - e.currentTarget.click() // simulate a click on the input - } - }} - /> -
- -
- ) - })} -
- ) - })} -
-
-
-
- ) -} - export const LabelSelector = (props: LabelsProps) => { const { id, formId, name, - className = '', defaultLabels = EMPTY_ARR, options = labelOptions, disabled, - subject, - ...others + onChange, } = props const [selectedLabels, setSelectedLabels] = useState( defaultLabels.map((label) => ({ @@ -186,6 +48,7 @@ export const LabelSelector = (props: LabelsProps) => { label).join(',') @@ -209,7 +72,12 @@ export const LabelSelector = (props: LabelsProps) => { ) }} - onChange={(value) => setSelectedLabels(value)} + onChange={(value) => { + setSelectedLabels(value) + onChange?.( + Array.isArray(value) ? value.map(({ value }) => value) : [], + ) + }} /> ) @@ -220,8 +88,7 @@ type LabelsProps = { formId: string name: string disabled?: boolean - className?: string defaultLabels?: string[] options?: string[] - subject?: string + onChange?: (labels: string[]) => void } diff --git a/components/mod-event/EventList.tsx b/components/mod-event/EventList.tsx index 8790e765..49658c34 100644 --- a/components/mod-event/EventList.tsx +++ b/components/mod-event/EventList.tsx @@ -7,7 +7,7 @@ import { import { LoadMoreButton } from '@/common/LoadMoreButton' import { ModEventItem } from './EventItem' import { Dropdown } from '@/common/Dropdown' -import { MOD_EVENT_TITLES } from './constants' +import { MOD_EVENTS, MOD_EVENT_TITLES } from './constants' import { ArchiveBoxXMarkIcon, ChevronDownIcon } from '@heroicons/react/20/solid' import { getSubjectTitle } from './helpers/subject' import { useState } from 'react' @@ -15,6 +15,9 @@ import { Checkbox, FormLabel, Input } from '@/common/forms' import { ActionButton } from '@/common/buttons' import { FunnelIcon as FunnelEmptyIcon } from '@heroicons/react/24/outline' import { FunnelIcon as FunnelFilledIcon } from '@heroicons/react/24/solid' +import { reasonTypeOptions } from '@/reports/helpers/getType' +import Select from 'react-tailwindcss-select' +import { LabelSelector } from '@/common/labels/Grid' const Header = ({ subjectTitle, @@ -65,6 +68,9 @@ export const ModEventList = ( ) => { const { types, + reportTypes, + addedLabels, + removedLabels, includeAllUserRecords, modEvents, fetchMoreModEvents, @@ -124,6 +130,9 @@ export const ModEventList = ( +
+ {types.includes(MOD_EVENTS.LABEL) && ( + <> + + + changeListFilter({ field: 'addedLabels', value }) + } + /> + + + + + changeListFilter({ field: 'removedLabels', value }) + } + /> + + + )} + + {types.includes(MOD_EVENTS.REPORT) && ( + +