このコミットが含まれているのは:
@@ -1,4 +1,5 @@
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { LoaderCircle } from 'lucide-react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
@@ -15,7 +16,8 @@ import Pagination from '@/components/common/Pagination'
|
||||
import MainArea from '@/components/layout/MainArea'
|
||||
import SidebarComponent from '@/components/layout/SidebarComponent'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { countsRequestParams, countsDefinitionParams, countsExportPayload, fieldsForCounts, fetchCounts,
|
||||
import { countsResourcePath, countsRequestParams, countsDefinitionParams,
|
||||
countsExportPayload, fieldsForCounts, fetchCounts,
|
||||
isCountsState, normaliseCountsParams, selectedCountColumns } from '@/lib/counts'
|
||||
import { countsErrorMessage, countsExportLabels } from '@/lib/countsDisplay'
|
||||
import { isApiError } from '@/lib/api'
|
||||
@@ -52,10 +54,10 @@ const tooManyColumns = (failure: unknown): number | null => {
|
||||
|
||||
|
||||
const CountsResourceContent = (
|
||||
{ resource, definition, definitionError }: {
|
||||
{ resource, definition, definitionError, definitionFailure }: {
|
||||
resource: CountsResource
|
||||
definition?: CountsDefinition
|
||||
definitionError: boolean },
|
||||
definitionError: boolean; definitionFailure?: unknown },
|
||||
) => {
|
||||
const queryClient = useQueryClient ()
|
||||
const [mounted, setMounted] = useState (false)
|
||||
@@ -106,7 +108,7 @@ const CountsResourceContent = (
|
||||
const requestKey = request.toString ()
|
||||
const [exporting, setExporting] = useState (false)
|
||||
const exportInFlight = useRef (false)
|
||||
const [exportError, setExportError] = useState (false)
|
||||
const [exportError, setExportError] = useState<{ failure: unknown } | null> (null)
|
||||
const { data: cachedData, error: queryError, dataUpdatedAt, isFetching: fetching,
|
||||
isPending: pending, isError: errorFlg,
|
||||
isPlaceholderData: placeholder } = useQuery ({
|
||||
@@ -236,7 +238,7 @@ const CountsResourceContent = (
|
||||
const waiting = running || (!definitionError && (definition == null
|
||||
|| pending || fetching || placeholder
|
||||
|| (!params.has ('execution_at') && !errorFlg)))
|
||||
const failure = runError ? runFailure : queryError
|
||||
const failure = definitionError ? definitionFailure : (runError ? runFailure : queryError)
|
||||
const failureMessage = countsErrorMessage (failure, locale)
|
||||
const columnLimit = runColumnLimit ?? tooManyColumns (queryError)
|
||||
|
||||
@@ -263,7 +265,7 @@ const CountsResourceContent = (
|
||||
|
||||
exportInFlight.current = true
|
||||
setExporting (true)
|
||||
setExportError (false)
|
||||
setExportError (null)
|
||||
try
|
||||
{
|
||||
const axes = [...readCountState<CountsAxis[]> (params, 'rows', []),
|
||||
@@ -291,9 +293,9 @@ const CountsResourceContent = (
|
||||
handle={handle} controls={controls}/> })
|
||||
|
||||
}
|
||||
catch
|
||||
catch (failure)
|
||||
{
|
||||
setExportError (true)
|
||||
setExportError ({ failure })
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -344,7 +346,7 @@ const CountsResourceContent = (
|
||||
return (
|
||||
<li key={definition}>
|
||||
<PrefetchLink
|
||||
to={`/counts/${target}?${next}`}
|
||||
to={`${countsResourcePath (target)}?${next}`}
|
||||
aria-current={active ? 'page' : undefined}
|
||||
className={cn ('block py-1', active && 'font-bold underline')}>
|
||||
{label (definition)}
|
||||
@@ -385,16 +387,20 @@ const CountsResourceContent = (
|
||||
{label (`exportFormats.${format}`)}</Button>)}
|
||||
</div>}/>}
|
||||
|
||||
{exportError && <p role="alert">{label ('common:fetchError')}</p>}
|
||||
{exportError != null && <p role="alert">
|
||||
{label ('errors.exportStart')}<br/>
|
||||
{countsErrorMessage (exportError.failure, locale).text}</p>}
|
||||
</div>
|
||||
{columnLimit != null ? <div role="alert">
|
||||
<p>{label ('columnLimit.title')}</p>
|
||||
<p>{label ('columnLimit.message', { max: columnLimit })}</p>
|
||||
</div> : ((definitionError || errorFlg || runError)
|
||||
&& <p role="alert" lang={failureMessage.language}>{failureMessage.text}</p>)}
|
||||
&& <p role="alert" lang={failureMessage.language}
|
||||
className="whitespace-pre-line">{failureMessage.text}</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">
|
||||
<div inert={waiting} aria-hidden={running || undefined}
|
||||
className={cn ('flex min-h-0 flex-1 flex-col', running && 'invisible')}>
|
||||
{mounted && definition != null && data != null && <>
|
||||
<p className="my-1 flex flex-wrap items-baseline gap-x-2 text-sm">
|
||||
<span>{label (resultMode === 'summary' ? 'outputRows' : 'outputTotal', { value: data.outputCount ?? '—' })}</span>
|
||||
@@ -413,10 +419,12 @@ const CountsResourceContent = (
|
||||
</>}
|
||||
</div>
|
||||
{waiting && <div role="status" aria-live="polite"
|
||||
className="pointer-events-none absolute right-2 top-2">
|
||||
className="pointer-events-none absolute inset-0 flex items-center justify-center">
|
||||
<span className="rounded border border-slate-300 bg-white px-2 py-1
|
||||
text-sm text-slate-900 dark:border-slate-600
|
||||
inline-flex items-center gap-2 text-sm text-slate-900 dark:border-slate-600
|
||||
dark:bg-slate-950 dark:text-slate-100">
|
||||
<LoaderCircle aria-hidden className={cn (
|
||||
'h-5 w-5', !motion.reduced && 'animate-spin')}/>
|
||||
{label ('shared:messages.loadingEllipsis')}</span>
|
||||
</div>}
|
||||
</div>
|
||||
@@ -428,11 +436,12 @@ const CountsResourceContent = (
|
||||
|
||||
const CountsResourcePage = ({ resource }: { resource: CountsResource }) => {
|
||||
const locale = useLocale ()
|
||||
const { data, isError: errorFlg } = useQuery ({
|
||||
const { data, error, isError: errorFlg } = useQuery ({
|
||||
queryKey: countsKeys.definition (resource, locale),
|
||||
queryFn: () => fetchCountsDefinition (resource, locale), staleTime: Infinity })
|
||||
return <CountsDefinitionContext.Provider value={data ?? null}>
|
||||
<CountsResourceContent resource={resource} definition={data} definitionError={errorFlg}/>
|
||||
<CountsResourceContent resource={resource} definition={data}
|
||||
definitionError={errorFlg} definitionFailure={error}/>
|
||||
</CountsDefinitionContext.Provider>
|
||||
}
|
||||
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする