このコミットが含まれているのは:
@@ -7,6 +7,7 @@ import CountsControls from '@/components/counts/CountsControls'
|
||||
import CountsSummaryResults from '@/components/counts/CountsSummaryResults'
|
||||
import CountsResults from '@/components/counts/CountsResults'
|
||||
import CountsTableLayout from '@/components/counts/CountsTableLayout'
|
||||
import AnimatedCollapse from '@/components/common/AnimatedCollapse'
|
||||
import PageHead from '@/components/common/PageHead'
|
||||
import PageTitle from '@/components/common/PageTitle'
|
||||
import Pagination from '@/components/common/Pagination'
|
||||
@@ -16,10 +17,12 @@ import { Button } from '@/components/ui/button'
|
||||
import { countsRequestParams, exportCounts, fieldsForCounts, fetchCounts,
|
||||
isCountsState, normaliseCountsParams, selectedCountColumns } from '@/lib/counts'
|
||||
import { countsExportLabels } from '@/lib/countsDisplay'
|
||||
import { countsAxisFields, countsResources, countsFieldLabel, readCountsJSON }
|
||||
import { CountsDefinitionContext, countsAxisFields, countsResources, countsFieldLabel,
|
||||
fetchCountsDefinition, readCountsJSON, useCountsDefinition }
|
||||
from '@/lib/countsDefinitions'
|
||||
import { countsKeys } from '@/lib/queryKeys'
|
||||
import { cn, inputClass } from '@/lib/utils'
|
||||
import { useClientMotion } from '@/lib/useClientMotion'
|
||||
import { useLocale } from '@/lib/useLocale'
|
||||
import { useUITranslation } from '@/lib/useUITranslation'
|
||||
|
||||
@@ -28,7 +31,8 @@ import type { CountsAxis } from '@/lib/countsDefinitions'
|
||||
import type { CountsResource } from '@/lib/counts'
|
||||
|
||||
|
||||
const CountsResourcePage = ({ resource }: { resource: CountsResource }) => {
|
||||
const CountsResourceContent = ({ resource }: { resource: CountsResource }) => {
|
||||
const definition = useCountsDefinition ()
|
||||
const [source, setParams] = useSearchParams ()
|
||||
const params = normaliseCountsParams (resource, source)
|
||||
const canonical = params.toString ()
|
||||
@@ -38,6 +42,11 @@ const CountsResourcePage = ({ resource }: { resource: CountsResource }) => {
|
||||
const request = countsRequestParams (params)
|
||||
const [open, setOpen] = useState (false)
|
||||
const [sidebarOpen, setSidebarOpen] = useState (false)
|
||||
const [expanded, setExpanded] = useState (() => new Set<string> ([resource]))
|
||||
const motion = useClientMotion ()
|
||||
useEffect (() => {
|
||||
setExpanded (previous => new Set ([...previous, resource]))
|
||||
}, [resource])
|
||||
const locale = useLocale ()
|
||||
const { label, message } = useUITranslation ('counts')
|
||||
const mode = params.get ('mode') ?? 'summary'
|
||||
@@ -57,7 +66,8 @@ const CountsResourcePage = ({ resource }: { resource: CountsResource }) => {
|
||||
&& previousParams.get ('mode') === mode
|
||||
&& previousParams.get ('rows') === params.get ('rows')
|
||||
&& previousParams.get ('cols') === params.get ('cols')
|
||||
&& previousParams.get ('definition') === cacheParams.get ('definition')) ? previous : undefined
|
||||
&& previousParams.get ('definition') === cacheParams.get ('definition'))
|
||||
? previous : undefined
|
||||
} })
|
||||
|
||||
useEffect (() => {
|
||||
@@ -99,13 +109,14 @@ const CountsResourcePage = ({ resource }: { resource: CountsResource }) => {
|
||||
...readCountsJSON<CountsAxis[]> (params, 'cols', [])].map (axis => ({
|
||||
key: axis.field, label: countsFieldLabel (axis.field) })),
|
||||
{ key: 'count', label: 'count' }]
|
||||
: selectedCountColumns (resource, params).map (column =>
|
||||
fieldsForCounts (resource).find (field => field.key === column)!)
|
||||
: selectedCountColumns (resource, params, definition).map (column =>
|
||||
fieldsForCounts (resource, definition).find (field => field.key === column)!)
|
||||
await exportCounts (resource, params, locale, format,
|
||||
fields.map (field => field.key), fields.map (field => message (field.label).text),
|
||||
{ ...countsExportLabels (resource, locale),
|
||||
...Object.fromEntries (countsAxisFields (resource, !state).map (field => [
|
||||
field.key, message (field.label).text])), count: message ('count').text })
|
||||
{ ...countsExportLabels (resource, locale, definition),
|
||||
...Object.fromEntries (countsAxisFields (definition, !state).map (field => [
|
||||
field.key, message (field.label).text])), count: message ('count').text },
|
||||
() => setExportError (true))
|
||||
|
||||
}
|
||||
catch
|
||||
@@ -133,11 +144,26 @@ const CountsResourcePage = ({ resource }: { resource: CountsResource }) => {
|
||||
<h2 className="mb-2 font-semibold">{label ('target')}</h2>
|
||||
<ul className="space-y-1">
|
||||
{countsResources.map (target => <li key={target}>
|
||||
<span>{label (`resources.${target}`)}</span>
|
||||
<button type="button" className="flex w-full items-center gap-1 py-1 text-left
|
||||
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500
|
||||
dark:focus-visible:ring-blue-400"
|
||||
aria-expanded={expanded.has (target)} aria-controls={`counts-definition-${target}`}
|
||||
onClick={() => setExpanded (previous => {
|
||||
const next = new Set (previous)
|
||||
if (next.has (target)) next.delete (target)
|
||||
else next.add (target)
|
||||
return next
|
||||
})}>
|
||||
<span aria-hidden className="inline-block" style={{
|
||||
transform: expanded.has (target) ? 'rotate(90deg)' : 'rotate(0deg)',
|
||||
transition: `transform ${motion.duration ('collapse')}ms ${motion.easing}` }}>▸</span>
|
||||
{label (`resources.${target}`)}
|
||||
</button>
|
||||
<AnimatedCollapse open={expanded.has (target)} id={`counts-definition-${target}`}>
|
||||
<ul className="ml-3">
|
||||
{['latest', 'history'].map (definition => {
|
||||
const next = new URLSearchParams ({ definition, mode })
|
||||
for (const key of ['timezone', 'at', 'execution_at'])
|
||||
for (const key of ['timezone', 'at'])
|
||||
if (params.get (key)) next.set (key, params.get (key)!)
|
||||
const active = target === resource
|
||||
&& params.get ('definition') === definition
|
||||
@@ -148,6 +174,7 @@ const CountsResourcePage = ({ resource }: { resource: CountsResource }) => {
|
||||
{label (definition)}</PrefetchLink></li>
|
||||
})}
|
||||
</ul>
|
||||
</AnimatedCollapse>
|
||||
</li>)}
|
||||
</ul>
|
||||
</nav>
|
||||
@@ -197,4 +224,17 @@ const CountsResourcePage = ({ resource }: { resource: CountsResource }) => {
|
||||
}
|
||||
|
||||
|
||||
const CountsResourcePage = ({ resource }: { resource: CountsResource }) => {
|
||||
const { label } = useUITranslation ('counts')
|
||||
const { data, isError } = useQuery ({
|
||||
queryKey: countsKeys.definition (resource),
|
||||
queryFn: () => fetchCountsDefinition (resource), staleTime: Infinity })
|
||||
if (data == null) return <p>{label (
|
||||
isError ? 'common:fetchError' : 'shared:messages.loadingEllipsis')}</p>
|
||||
return <CountsDefinitionContext.Provider value={data}>
|
||||
<CountsResourceContent resource={resource}/>
|
||||
</CountsDefinitionContext.Provider>
|
||||
}
|
||||
|
||||
|
||||
export default CountsResourcePage
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする