このコミットが含まれているのは:
2026-10-28 21:54:35 +09:00
コミット d0d1738192
6個のファイルの変更、51行の追加、20行の削除
+26 -4
ファイルの表示
@@ -18,6 +18,7 @@ import { Button } from '@/components/ui/button'
import { countsRequestParams, countsDefinitionParams, countsExportPayload, fieldsForCounts, fetchCounts,
isCountsState, normaliseCountsParams, selectedCountColumns } from '@/lib/counts'
import { countsExportLabels } from '@/lib/countsDisplay'
import { isApiError } from '@/lib/api'
import { CountsDefinitionContext, countsAxisFields, countsAxisLabel,
visibleCountsResources, countsFieldLabel,
fetchCountsDefinition }
@@ -42,6 +43,16 @@ type PendingCountsRun = {
target?: string }
const tooManyColumns = (failure: unknown): number | null => {
if (!isApiError (failure) || failure.response?.status !== 422) return null
const body = (failure.response.data ?? { }) as {
error?: unknown; maxColumns?: unknown; max_columns?: unknown }
const maximum = body.maxColumns ?? body.max_columns
return body.error === 'too_many_columns' && typeof maximum === 'number'
? maximum : null
}
const CountsResourceContent = (
{ resource, definition, definitionError }: {
resource: CountsResource; definition?: CountsDefinition; definitionError: boolean },
@@ -85,6 +96,7 @@ const CountsResourceContent = (
cacheParams.set ('definition', state ? 'latest' : 'history')
const [running, setRunning] = useState (false)
const [runError, setRunError] = useState (false)
const [runColumnLimit, setRunColumnLimit] = useState<number | null> (null)
const pendingRun = useRef<PendingCountsRun | null> (null)
const applied = useRef (params)
const retainedParams = useRef (params)
@@ -92,7 +104,8 @@ const CountsResourceContent = (
const [exporting, setExporting] = useState (false)
const exportInFlight = useRef (false)
const [exportError, setExportError] = useState (false)
const { data, dataUpdatedAt, isFetching: fetching, isPending: pending, isError: errorFlg,
const { data, error: queryError, dataUpdatedAt, isFetching: fetching,
isPending: pending, isError: errorFlg,
isPlaceholderData: placeholder } = useQuery ({
enabled: definition != null && params.has ('timezone') && !running,
staleTime: params.has ('execution_at') ? 5 * 60 * 1000 : 0,
@@ -124,6 +137,7 @@ const CountsResourceContent = (
useEffect (() => {
setRunning (false)
setRunError (false)
setRunColumnLimit (null)
return () => {
const pending = pendingRun.current
pendingRun.current = null
@@ -162,6 +176,7 @@ const CountsResourceContent = (
const previous = new URLSearchParams (params)
pendingRun.current = pending
setRunError (false)
setRunColumnLimit (null)
setRunning (true)
try
{
@@ -199,11 +214,12 @@ const CountsResourceContent = (
}
else setParams (committed, { preventScrollReset: true })
}
catch
catch (failure)
{
if (pendingRun.current !== pending) return
pendingRun.current = null
setRunning (false)
setRunColumnLimit (tooManyColumns (failure))
setRunError (true)
}
}
@@ -212,9 +228,11 @@ const CountsResourceContent = (
const waiting = running || (!definitionError && (definition == null
|| pending || fetching || placeholder
|| (!params.has ('execution_at') && !errorFlg)))
const columnLimit = runColumnLimit ?? tooManyColumns (queryError)
const update = (key: string, value: string, extra?: Record<string, string>) => {
setRunColumnLimit (null)
const next = new URLSearchParams (params)
if (value || ['sort', 'columns', 'children', 'conditions', 'drill'].includes (key))
setCountState (next, key, value)
@@ -275,7 +293,7 @@ const CountsResourceContent = (
<CountsTableLayout>
<div data-sidebar-container
className="flex min-h-0 flex-1 flex-col overflow-hidden md:flex-row">
<PageHead title={title} includeSiteName={false}/>
<PageHead title={title}/>
<Button type="button" variant="ghost" size="sm" className="shrink-0 md:hidden"
aria-expanded={sidebarOpen} aria-controls="counts-targets"
onClick={() => setSidebarOpen (!sidebarOpen)}>{label ('target')}</Button>
@@ -347,7 +365,11 @@ const CountsResourceContent = (
{exportError && <p role="alert">{label ('common:fetchError')}</p>}
</div>
{(definitionError || errorFlg || runError) && <p role="alert">{label ('common:fetchError')}</p>}
{columnLimit != null ? <div role="alert">
<p>{label ('columnLimit.title')}</p>
<p>{label ('columnLimit.message', { max: columnLimit })}</p>
</div> : ((definitionError || errorFlg || runError)
&& <p role="alert">{label ('common:fetchError')}</p>)}
<div className="relative flex min-h-0 flex-1 flex-col overflow-hidden"
aria-busy={waiting}>
<div inert={waiting} className="flex min-h-0 flex-1 flex-col">