このコミットが含まれているのは:
2026-10-25 22:16:20 +09:00
コミット 96a5bb8601
12個のファイルの変更、600行の追加、25行の削除
+16 -9
ファイルの表示
@@ -1,10 +1,11 @@
import { useEffect, useId, useState } from 'react'
import CountsStateFilters from '@/components/counts/CountsStateFilters'
import CountsFieldTree from '@/components/counts/CountsFieldTree'
import DateTimeField from '@/components/common/DateTimeField'
import FormField from '@/components/common/FormField'
import { Button } from '@/components/ui/button'
import { normaliseCountsParams } from '@/lib/counts'
import { isCountsState, normaliseCountsParams } from '@/lib/counts'
import { fetchTagByName } from '@/lib/tags'
import { inputClass } from '@/lib/utils'
import { useLocale } from '@/lib/useLocale'
@@ -42,7 +43,8 @@ const CountsControls = (
}, [order, nestedJSON])
const [error, setError] = useState (false)
const [pending, setPending] = useState (false)
const mode = draft.get ('mode') ?? 'summary'
const mode = draft.get ('mode') ?? 'state'
const state = isCountsState (draft)
const update = (key: string, value: string) => {
setDraft (previous => {
const next = new URLSearchParams (previous)
@@ -58,11 +60,12 @@ const CountsControls = (
try
{
const next = new URLSearchParams (draft)
for (const key of resource === 'posts' ? ['tag'] : ['resource_id'])
for (const key of (state || resource === 'posts') ? ['tag'] : ['resource_id'])
{
const value = next.get (key)?.trim () ?? ''
if (value && !/^[1-9][0-9]*$/.test (value))
{
if (state && next.get ('kind') === 'external') throw new Error ()
const tag = await fetchTagByName (value, locale)
if (tag == null)
throw new Error ()
@@ -96,10 +99,10 @@ const CountsControls = (
<select className={inputClass (false, 'w-auto py-1')}
aria-label={message ('mode').text} lang={message ('mode').language}
value={mode} onChange={event => update ('mode', event.target.value)}>
<option value="summary" lang={message ('summary').language}>
{message ('summary').text}</option>
<option value="details" lang={message ('details').language}>
{message ('details').text}</option>
{[['state', 'summary'], ['trend', 'state.trend'], ['snapshot', 'state.details'],
['summary', 'state.history'], ['details', 'state.historyDetails']].map (
([value, key]) => <option key={value} value={value} lang={message (key).language}>
{message (key).text}</option>)}
</select>
</div>
{error && <p role="alert">{label ('shared:messages.checkInputModern')}</p>}
@@ -115,7 +118,9 @@ const CountsControls = (
}}/>
{label ('nested.asJSON')}
</label>
{mode === 'summary' ? (
{(mode === 'state' || mode === 'trend') ? (
<p className="text-sm">{label (
mode === 'trend' ? 'state.trend' : 'state.list')}</p>) : (mode === 'summary' ? (
<label className="flex flex-wrap items-center gap-2">
{label ('axis')}
<select className={inputClass (false, 'w-auto py-1')}
@@ -130,10 +135,11 @@ const CountsControls = (
<CountsFieldTree resource={resource} params={draft} update={(key, value) => {
update (key, value)
if (key === 'order') reorder (value)
}}/>)}
}}/>))}
</fieldset>
<fieldset className="min-w-0 space-y-2" data-counts-filters>
<legend className="mb-2 font-semibold">{label ('filters')}</legend>
{state ? <CountsStateFilters params={draft} update={update}/> : <>
<label className="flex items-center gap-1">
<input type="checkbox" checked={draft.get ('latest') !== '0'}
onChange={event => update ('latest', event.target.checked ? '1' : '0')}/>
@@ -161,6 +167,7 @@ const CountsControls = (
className={inputClass (false, 'py-1')}/>}
</FormField>))}
</div>
</>}
</fieldset>
</div>
</div>