このコミットが含まれているのは:
2026-10-29 12:28:20 +09:00
コミット 7536330ecf
8個のファイルの変更、99行の追加、32行の削除
+33 -1
ファイルの表示
@@ -7,6 +7,9 @@ import { countsConditionInputs, countsEventTypes, countsFieldLabel, countsFilter
countsSetOperators, useCountsDefinition }
from '@/lib/countsDefinitions'
import useDialogue from '@/lib/dialogues/useDialogue'
import { countsSummaryValue } from '@/lib/countsDisplay'
import { countsAxisLabel } from '@/lib/countsDefinitions'
import { useLocale } from '@/lib/useLocale'
import { inputClass } from '@/lib/utils'
import { useUITranslation } from '@/lib/useUITranslation'
@@ -97,6 +100,7 @@ const CountsAdditionalConditions = ({ params, update }: {
const { label, message } = useUITranslation ('counts')
const definition = useCountsDefinition ()
const dialogue = useDialogue ()
const locale = useLocale ()
const conditions = readCountState<CountsCondition[]> (params, 'conditions', [])
const metadata = definition.filterFields ?? definition.fields
const fields = metadata.filter (field => field.operators.length > 0 && !field.legacy)
@@ -153,7 +157,35 @@ const CountsAdditionalConditions = ({ params, update }: {
<legend className="flex items-center gap-2">{label ('additionalConditions')}
<Button type="button" variant="outline" size="sm" disabled={fields.length === 0}
onClick={() => edit ()}>{label ('add')}</Button></legend>
{conditions.map ((condition, index) => (
{params.get ('tags') && params.get ('match') && <div
className="flex items-center gap-2">
<span>match = {params.get ('match')}</span>
<Button type="button" variant="ghost" size="sm"
aria-label={message ('remove').text} onClick={() => update ('match', '')}>×</Button>
</div>}
{readCountState<Record<string, string | number | boolean>[]> (
params, 'tag_refs', []).map ((reference, index, references) => (
<div key={`reference-${index}`} className="flex flex-wrap items-center gap-2">
<span>{Object.entries (reference).map (([key, value]) =>
`${key}=${value}`).join (' ')}</span>
<Button type="button" variant="ghost" size="sm"
aria-label={message ('remove').text}
onClick={() => update ('tag_refs', encodeCountState ('tag_refs',
references.filter ((_, position) => position !== index)))}>×</Button>
</div>))}
{conditions.map ((condition, index) => condition.operator === 'axis_eq' ? (
<div key={index} className="flex flex-wrap items-center gap-2 border-b py-2">
<span>{countsAxisLabel (condition, definition, locale).text}</span>
<span>{label ('operatorSymbols.eq')}</span>
<span>{condition.value == null ? 'NULL' : (condition.field === 'tags'
? condition.value : countsSummaryValue (
condition.value, condition, 0, { count: 0, page: 1, limit: 100 }, locale,
params.get ('timezone') ?? 'UTC'))}</span>
<Button type="button" variant="ghost" size="sm"
aria-label={message ('remove').text}
onClick={() => write (conditions.filter ((_, position) => position !== index))}>
×</Button>
</div>) : (
<div key={index} className="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-2
border-b border-slate-200 py-2 dark:border-slate-700">
<Button type="button" variant="ghost" size="sm" onClick={() => edit (index)}
+4 -4
ファイルの表示
@@ -86,10 +86,10 @@ const CountsSummaryTable = (
: totals.get (JSON.stringify ([row.values, column.values])) ?? 0
const drill = (row: CountsPivotHeader, column: CountsPivotHeader) => {
const next = new URLSearchParams (params)
const existing = readCountState<Record<string, string | number | null>[]> (params, 'drill', [])
setCountState (next, 'drill', encodeCountState ('drill', [...existing,
...row.values.map ((value, index) => ({ ...rows[index], value })),
...column.values.map ((value, index) => ({ ...cols[index], value }))]))
const existing = readCountState<Record<string, string | number | null>[]> (params, 'conditions', [])
setCountState (next, 'conditions', encodeCountState ('conditions', [...existing,
...row.values.map ((value, index) => ({ ...rows[index], operator: 'axis_eq', value })),
...column.values.map ((value, index) => ({ ...cols[index], operator: 'axis_eq', value }))]))
next.set ('mode', 'details')
next.delete ('sort')
next.delete ('page')