このコミットが含まれているのは:
@@ -17,11 +17,12 @@ import { Button } from '@/components/ui/button'
|
||||
import { countsRequestParams, defaultCountsMode, exportCounts, fieldsForCounts, fetchCounts,
|
||||
isCountsState, normaliseCountsParams, selectedCountColumns } from '@/lib/counts'
|
||||
import { countsExportLabels } from '@/lib/countsDisplay'
|
||||
import { CountsDefinitionContext, countsAxisFields, countsResources, countsFieldLabel,
|
||||
import { CountsDefinitionContext, countsAxisFields, countsAxisLabel,
|
||||
countsResources, countsFieldLabel,
|
||||
fetchCountsDefinition, readCountsJSON, useCountsDefinition }
|
||||
from '@/lib/countsDefinitions'
|
||||
import { countsKeys } from '@/lib/queryKeys'
|
||||
import { cn, inputClass } from '@/lib/utils'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { useClientMotion } from '@/lib/useClientMotion'
|
||||
import { useLocale } from '@/lib/useLocale'
|
||||
import { useUITranslation } from '@/lib/useUITranslation'
|
||||
@@ -54,7 +55,6 @@ const CountsResourceContent = ({ resource }: { resource: CountsResource }) => {
|
||||
const state = isCountsState (params)
|
||||
const cacheParams = new URLSearchParams (request)
|
||||
cacheParams.set ('definition', state ? 'latest' : 'history')
|
||||
const [format, setFormat] = useState<'json' | 'csv'> ('json')
|
||||
const [exporting, setExporting] = useState (false)
|
||||
const [exportError, setExportError] = useState (false)
|
||||
const { data, isPending, isError, isPlaceholderData, refetch } = useQuery ({
|
||||
@@ -100,20 +100,25 @@ const CountsResourceContent = ({ resource }: { resource: CountsResource }) => {
|
||||
if (key === 'sort') next.delete ('page')
|
||||
setParams (next)
|
||||
}
|
||||
const download = async () => {
|
||||
const download = async (format: 'csv' | 'json') => {
|
||||
setExporting (true)
|
||||
setExportError (false)
|
||||
try
|
||||
{
|
||||
const axes = [...readCountsJSON<CountsAxis[]> (params, 'rows', []),
|
||||
...readCountsJSON<CountsAxis[]> (params, 'cols', [])]
|
||||
const fields = mode === 'summary' ? [
|
||||
...[...readCountsJSON<CountsAxis[]> (params, 'rows', []),
|
||||
...readCountsJSON<CountsAxis[]> (params, 'cols', [])].map (axis => ({
|
||||
...axes.map (axis => ({
|
||||
key: axis.field, label: countsFieldLabel (axis.field) })),
|
||||
{ key: 'count', label: 'count' }]
|
||||
: selectedCountColumns (resource, params, definition).map (column =>
|
||||
fieldsForCounts (resource, definition).find (field => field.key === column)!)
|
||||
const headers = mode === 'summary'
|
||||
? [...axes.map (axis => countsAxisLabel (axis, definition, locale).text),
|
||||
message ('count').text]
|
||||
: fields.map (field => message (field.label).text)
|
||||
await exportCounts (resource, params, locale, format,
|
||||
fields.map (field => field.key), fields.map (field => message (field.label).text),
|
||||
fields.map (field => field.key), headers,
|
||||
{ ...countsExportLabels (resource, locale, definition),
|
||||
...Object.fromEntries (countsAxisFields (definition, !state).map (field => [
|
||||
field.key, message (field.label).text])), count: message ('count').text },
|
||||
@@ -193,20 +198,15 @@ const CountsResourceContent = ({ resource }: { resource: CountsResource }) => {
|
||||
execute={next => {
|
||||
if (next.toString () === canonical) void refetch ()
|
||||
else setParams (next)
|
||||
}} actions={<>
|
||||
<select value={format} aria-label={message ('exportFormat').text}
|
||||
lang={message ('exportFormat').language}
|
||||
className={inputClass (false, 'w-auto py-1')}
|
||||
onChange={event => setFormat (event.target.value as 'json' | 'csv')}>
|
||||
{(['json', 'csv'] as const).map (value => (
|
||||
<option key={value} value={value}>
|
||||
{message (`exportFormats.${value}`).text}</option>))}
|
||||
</select>
|
||||
<Button type="button" variant="outline" size="sm"
|
||||
}} actions={<div className="ml-auto flex shrink-0 items-center gap-2">
|
||||
{(['csv', 'json'] as const).map (format => <Button key={format}
|
||||
type="button" variant="outline" size="sm"
|
||||
disabled={data == null || isError || isPlaceholderData
|
||||
|| exporting || !params.get ('execution_at')}
|
||||
onClick={() => void download ()}>{label ('export')}</Button>
|
||||
</>}/>
|
||||
onClick={() => void download (format)}>
|
||||
{label (`exportFormats.${format}`)}</Button>)}
|
||||
</div>}/>
|
||||
|
||||
{exportError && <p role="alert">{label ('common:fetchError')}</p>}
|
||||
</div>
|
||||
{isPending && <p>{label ('shared:messages.loadingEllipsis')}</p>}
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする