Skip to content

Commit

Permalink
✨ Advanced tag filters (#266)
Browse files Browse the repository at this point in the history
* 🚧 WIP

* 🐛 Ignore keybinding for takedown unless user has permission

* ✨ Remove cmd palette shortcuts

* 💄 Fix styling for tetris page for dark mode

* 💄 Fix tag list overflow in profile page

* 💄 De-emphasize bluesky branding

* ✨ Add tag filtering with exclusion

* 🧹 Cleanup

* ✨ Show filters preview

* ✨ Add arbitrary tag input
  • Loading branch information
foysalit authored Jan 8, 2025
1 parent 73d4003 commit 63146b2
Show file tree
Hide file tree
Showing 18 changed files with 451 additions and 298 deletions.
23 changes: 16 additions & 7 deletions app/actions/ModActionPanel/QuickAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
ChevronUpIcon,
} from '@heroicons/react/24/outline'
import { LabelSelector } from '@/common/labels/Selector'
import { pluralize, takesKeyboardEvt } from '@/lib/util'
import { takesKeyboardEvt } from '@/lib/util'
import { Loading } from '@/common/Loader'
import { ActionDurationSelector } from '@/reports/ModerationForm/ActionDurationSelector'
import { MOD_EVENTS } from '@/mod-event/constants'
Expand Down Expand Up @@ -201,6 +201,7 @@ function Form(
const shouldShowDurationInHoursField =
isTakedownEvent || isMuteEvent || isMuteReporterEvent
const canManageChat = usePermission('canManageChat')
const canTakedown = usePermission('canTakedown')

// navigate to next or prev report
const navigateQueue = (delta: 1 | -1) => {
Expand Down Expand Up @@ -500,7 +501,13 @@ function Form(
submitForm()
}
useKeyPressEvent('c', safeKeyHandler(onCancel))
useKeyPressEvent('s', safeKeyHandler(submitForm))
useKeyPressEvent(
's',
safeKeyHandler((e) => {
e.stopImmediatePropagation()
submitForm()
}),
)
useKeyPressEvent('n', safeKeyHandler(submitAndGoNext))
useKeyPressEvent(
'a',
Expand All @@ -522,9 +529,11 @@ function Form(
)
useKeyPressEvent(
't',
safeKeyHandler(() => {
setModEventType(MOD_EVENTS.TAKEDOWN)
}),
canTakedown
? safeKeyHandler(() => {
setModEventType(MOD_EVENTS.TAKEDOWN)
})
: undefined,
)

return (
Expand Down Expand Up @@ -644,8 +653,8 @@ function Form(
{!!subjectStatus?.tags?.length && (
<div className={`mb-3`}>
<FormLabel label="Tags">
<LabelList className="-ml-1 flex-wrap">
{subjectStatus.tags.map((tag) => {
<LabelList className="-ml-1 flex-wrap gap-1">
{subjectStatus.tags.sort().map((tag) => {
return <SubjectTag key={tag} tag={tag} />
})}
</LabelList>
Expand Down
38 changes: 2 additions & 36 deletions app/surprise-me/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const Timer = () => {
}, 1000)

return (
<div className="flex flex-row justify-center py-4">
<div className="flex flex-row justify-center py-4 dark:text-gray-200">
<p className="font-bold text-xl">{getDuration(seconds)}</p>
</div>
)
Expand All @@ -44,41 +44,7 @@ export default function SurpriseMePage() {
<>
{/* This is valid jsx but because of a known bug, typescript is confused */}
{/* @ts-ignore:next-line */}
<style global jsx>
{`
.game-block {
margin: 0;
padding: 0;
width: 1.5em;
height: 1.5em;
border: 1px solid #ddd;
}
.piece-i {
background-color: #ec858b;
}
.piece-j {
background-color: #f1b598;
}
.piece-l {
background-color: #f8efae;
}
.piece-o {
background-color: #b5a677;
}
.piece-s {
background-color: #816e56;
}
.piece-t {
background-color: #b77c72;
}
.piece-z {
background-color: #e3be58;
}
.piece-preview {
background-color: #eee;
}
`}
</style>

<Timer />
<ClientOnlyTetris />
</>
Expand Down
4 changes: 2 additions & 2 deletions components/common/SetupModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ export function SetupModal({
className="mx-auto h-20 w-auto"
title="Icon from Flaticon: https://www.flaticon.com/free-icons/lifeguard-tower"
src="/img/logo-colorful.png"
alt="Ozone - Bluesky Admin"
alt="Ozone - ATProto Moderation Service"
width={200}
height={200}
/>
<h2 className="mt-6 text-center text-3xl font-bold tracking-tight text-gray-900 dark:text-gray-200">
Bluesky Admin Tools
Ozone Moderation Service
</h2>
{title && (
<p className="mt-2 text-center text-sm text-gray-600 dark:text-gray-100">
Expand Down
2 changes: 1 addition & 1 deletion components/entertainment/tetris.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default function TetrisGame () {
state,
controller,
}) => (
<div className="flex flex-row gap-x-4 items-start pt-4 mx-auto">
<div className="flex flex-row gap-x-4 items-start pt-4 mx-auto dark:text-gray-200">
<HeldPiece />
<div>
<p>Points: {points}</p>
Expand Down
103 changes: 0 additions & 103 deletions components/reports/QueueFilter/Language.tsx

This file was deleted.

66 changes: 46 additions & 20 deletions components/reports/QueueFilter/Panel.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,40 @@
import { Popover, Transition } from '@headlessui/react'
import { ChevronDownIcon } from '@heroicons/react/20/solid'
import { QueueFilterLanguage } from './Language'
import { QueueFilterSubjectType } from './SubjectType'
import { useSearchParams } from 'next/navigation'
import { useQueueFilterBuilder } from '../useQueueFilter'
import { ToolsOzoneModerationQueryStatuses } from '@atproto/api'
import { getLanguageFlag } from 'components/tags/SubjectTag'
import { getCollectionName } from '../helpers/subject'
import { classNames } from '@/lib/util'
import { QueueFilterTags } from './Tag'

const buildTagFilterSummary = (tags: string[]) => {
const filtered = tags.filter(Boolean)
if (!filtered.length) {
return ''
}

const list = filtered.map((tag) => {
return tag
.split('&&')
.map((t) => {
t = t.trim()
if (t.startsWith('lang:')) {
const langCode = t.split(':')[1]
return getLanguageFlag(langCode) || t
}
return t
})
.join(' AND ')
})

if (list.length === 1) {
return list[0]
}

return `(${list.join(') OR (')})`
}

// Takes all the queue filters manageable in the panel and displays a summary of selections made
const FilterSummary = ({
Expand All @@ -17,7 +44,7 @@ const FilterSummary = ({
}) => {
const { tags, excludeTags, collections, subjectType } = queueFilters
if (
!tags?.length &&
!tags?.filter(Boolean).length &&
!excludeTags?.length &&
!collections?.length &&
!subjectType
Expand All @@ -36,51 +63,49 @@ const FilterSummary = ({
inclusions.push('Only Records')
}

tags?.forEach((tag) => {
if (tag.startsWith('lang:')) {
const langCode = tag.split(':')[1]
inclusions.push(getLanguageFlag(langCode) || langCode)
}

if (tag.startsWith('embed:')) {
inclusions.push(tag.split(':')[1])
}
})
if (tags?.length) {
inclusions.push(buildTagFilterSummary(tags))
}

excludeTags?.forEach((tag) => {
if (tag.startsWith('lang:')) {
const langCode = tag.split(':')[1]
exclusions.push(getLanguageFlag(langCode) || langCode)
return
}

if (tag.startsWith('embed:')) {
exclusions.push(tag.split(':')[1])
return
}

exclusions.push(tag)
})

return (
<>
{!!inclusions.length && inclusions.join(' ')}
{!!exclusions.length && (
{!!collections?.length && (
<span
className={classNames(
'line-through opacity-50',
inclusions.length
? 'border-l border-gray-400 ml-1 pl-1'
: undefined,
)}
>
{exclusions.join(' ')}
Collections: {collections.map(getCollectionName).join(', ')}
</span>
)}
{!!collections?.length && (
{!!exclusions.length && (
<span
className={classNames(
'line-through opacity-50',
inclusions.length
? 'border-l border-gray-400 ml-1 pl-1'
: undefined,
)}
>
Collections: {collections.map(getCollectionName).join(', ')}
{exclusions.join(' ')}
</span>
)}
</>
Expand Down Expand Up @@ -117,12 +142,13 @@ export const QueueFilterPanel = () => {
leaveFrom="transform scale-100 opacity-100"
leaveTo="transform scale-95 opacity-0"
>
<Popover.Panel className="absolute left-0 z-10 mt-1 flex w-screen max-w-max -translate-x-1/5 px-4">
<div className="w-fit-content flex-auto rounded bg-white dark:bg-slate-800 p-4 text-sm leading-6 shadow-lg dark:shadow-slate-900 ring-1 ring-gray-900/5">
<Popover.Panel className="absolute left-0 z-10 mt-1 flex max-w-max -translate-x-1/5 px-4">
<div className="flex-auto w-96 rounded bg-white dark:bg-slate-800 p-4 text-sm leading-6 shadow-lg dark:shadow-slate-900 ring-1 ring-gray-900/5">
<div className="flex flex-row px-2 gap-6">
<QueueFilterLanguage />
<QueueFilterSubjectType />
</div>

<QueueFilterTags />
</div>
</Popover.Panel>
</Transition>
Expand Down
Loading

0 comments on commit 63146b2

Please sign in to comment.