このコミットが含まれているのは:
2026-11-01 00:20:32 +09:00
コミット 74c5242828
22個のファイルの変更、202行の追加、232行の削除
+4 -9
ファイルの表示
@@ -68,22 +68,17 @@ describe ('Counts filter draft', () => {
expect (screen.queryByText ('pattern.input')).not.toBeInTheDocument ()
})
it ('retains stable references only for surviving search tokens', () => {
const params = appliedParams ({ tags: 'alpha beta' })
setCountState (params, 'tag_refs', encodeCountState ('tag_refs', [
{ name: 'alpha', tag_id: 7 }, { name: 'beta', external_tag_id: 8 }]))
const { execute } = renderControls (params)
it ('submits only the edited tag names', () => {
const { execute } = renderControls (appliedParams ({ tags: 'alpha beta' }))
const tags = screen.getByDisplayValue ('alpha beta')
fireEvent.change (tags, { target: { value: 'not:beta gamma alpha' } })
submit ()
expect (readCountState (execute.mock.lastCall![0], 'tag_refs', [])).toEqual ([
{ name: 'alpha', tag_id: 7 }, { name: 'not:beta', external_tag_id: 8, negative: true }])
expect (execute.mock.lastCall![0].get ('tags')).toBe ('not:beta gamma alpha')
fireEvent.change (tags, { target: { value: 'gamma' } })
submit ()
expect (readCountState (execute.mock.lastCall![0], 'tag_refs', [])).toEqual ([])
expect (execute.mock.lastCall![0].get ('tags')).toBe ('gamma')
expect (screen.queryByText (/internal:7|external:8/)).not.toBeInTheDocument ()
})
})
+2 -24
ファイルの表示
@@ -17,7 +17,7 @@ import { useClientMotion } from '@/lib/useClientMotion'
import { inputClass } from '@/lib/utils'
import { useUITranslation } from '@/lib/useUITranslation'
import { readCountState, setCountState, encodeCountState } from '@/lib/queryState'
import { readCountState, setCountState } from '@/lib/queryState'
import type { ReactNode } from 'react'
@@ -97,27 +97,6 @@ const CountsControls = (
const update = (key: string, value: string) => setDraft (previous => {
const next = new URLSearchParams (previous)
setCountState (next, key, value)
if (key === 'tags')
{
const tokens = value.split (/\s+/).filter (token => token
&& token.toLowerCase () !== 'type:or')
const remaining = [...tokens]
const references = readCountState<Record<string, string | number | boolean>[]> (
previous, 'tag_refs', []).flatMap (reference => {
const name = String (reference.name)
const exact = remaining.indexOf (name)
const index = exact >= 0 ? exact : remaining.findIndex (token =>
token.replace (/^not:/i, '') === name.replace (/^not:/i, ''))
if (index < 0) return []
const [token] = remaining.splice (index, 1)
return [token === name ? reference : { ...reference, name: token,
negative: token.toLowerCase ().startsWith ('not:') }]
})
for (const name of [...next.keys ()])
if (name === 'tag_refs' || name.startsWith ('tag_refs.')) next.delete (name)
if (references.length > 0)
setCountState (next, 'tag_refs', encodeCountState ('tag_refs', references))
}
if (key === 'limit') next.delete ('page')
if (next.toString () === previous.toString ()) return previous
if (['rows', 'cols'].includes (key) && next.get ('sort') !== '') next.delete ('sort')
@@ -278,8 +257,7 @@ const CountsControls = (
aria-label={message ('remove').text} onClick={() => setDraft (previous => {
const next = new URLSearchParams (previous)
for (const key of [...next.keys ()])
if (['tags', 'tag', 'kind', 'match', 'tag_refs', 'page'].includes (key)
|| key.startsWith ('tag_refs.')) next.delete (key)
if (['tags', 'tag', 'kind', 'match', 'page'].includes (key)) next.delete (key)
return next
})}>×</Button>
</>}