このコミットが含まれているのは:
@@ -9,7 +9,6 @@ import { CSS } from '@dnd-kit/utilities'
|
|||||||
|
|
||||||
import SortableItem from '@/components/common/SortableItem'
|
import SortableItem from '@/components/common/SortableItem'
|
||||||
import { useClientMotion } from '@/lib/useClientMotion'
|
import { useClientMotion } from '@/lib/useClientMotion'
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
|
|
||||||
import type { ReactNode } from 'react'
|
import type { ReactNode } from 'react'
|
||||||
|
|
||||||
@@ -19,8 +18,10 @@ type Name = { text: string; language: string }
|
|||||||
|
|
||||||
const sameGroups = (left: Groups, right: Groups): boolean =>
|
const sameGroups = (left: Groups, right: Groups): boolean =>
|
||||||
Object.keys (left).length === Object.keys (right).length
|
Object.keys (left).length === Object.keys (right).length
|
||||||
&& Object.keys (left).every (key => left[key].length === right[key]?.length
|
&& (
|
||||||
&& left[key].every ((id, index) => id === right[key][index]))
|
Object.keys (left).every (key => (
|
||||||
|
left[key].length === right[key]?.length
|
||||||
|
&& left[key].every ((id, index) => id === right[key][index]))))
|
||||||
|
|
||||||
|
|
||||||
const Group = ({ id, children }: { id: string; children: ReactNode }) => {
|
const Group = ({ id, children }: { id: string; children: ReactNode }) => {
|
||||||
@@ -87,7 +88,10 @@ const SortableList = (
|
|||||||
setActive (null)
|
setActive (null)
|
||||||
setOverGroup (null)
|
setOverGroup (null)
|
||||||
}
|
}
|
||||||
return <DndContext sensors={sensors} collisionDetection={args => {
|
return (
|
||||||
|
<DndContext
|
||||||
|
sensors={sensors}
|
||||||
|
collisionDetection={args => {
|
||||||
const hits = pointerWithin (args)
|
const hits = pointerWithin (args)
|
||||||
const group = hits.find (hit => String (hit.id).startsWith ('group:'))
|
const group = hits.find (hit => String (hit.id).startsWith ('group:'))
|
||||||
const groupName = group?.id.toString ().slice (6)
|
const groupName = group?.id.toString ().slice (6)
|
||||||
@@ -109,7 +113,8 @@ const SortableList = (
|
|||||||
drag.current = { id, groups }
|
drag.current = { id, groups }
|
||||||
setActive (id)
|
setActive (id)
|
||||||
setOverGroup (owner (id, groups) ?? null)
|
setOverGroup (owner (id, groups) ?? null)
|
||||||
}} onDragOver={event => {
|
}}
|
||||||
|
onDragOver={event => {
|
||||||
const id = event.over?.id.toString ()
|
const id = event.over?.id.toString ()
|
||||||
const group = id == null ? null
|
const group = id == null ? null
|
||||||
: (id.startsWith ('group:') ? id.slice (6) : owner (id, groups) ?? null)
|
: (id.startsWith ('group:') ? id.slice (6) : owner (id, groups) ?? null)
|
||||||
@@ -122,7 +127,6 @@ const SortableList = (
|
|||||||
const next = relocate (groups, session.id, String (event.over.id))
|
const next = relocate (groups, session.id, String (event.over.id))
|
||||||
if (!sameGroups (groups, next)) onChange (next)
|
if (!sameGroups (groups, next)) onChange (next)
|
||||||
}}>
|
}}>
|
||||||
|
|
||||||
{/* Keep indexes and droppable geometry stable until the drop is committed. */}
|
{/* Keep indexes and droppable geometry stable until the drop is committed. */}
|
||||||
{Object.entries (groups).map (([group, ids]) => <Group key={group} id={group}>
|
{Object.entries (groups).map (([group, ids]) => <Group key={group} id={group}>
|
||||||
{renderGroup (group, <SortableContext items={ids} strategy={rectSortingStrategy}>
|
{renderGroup (group, <SortableContext items={ids} strategy={rectSortingStrategy}>
|
||||||
@@ -149,7 +153,7 @@ const SortableList = (
|
|||||||
text-slate-900 shadow-lg dark:border-blue-400 dark:bg-slate-800 dark:text-slate-100">
|
text-slate-900 shadow-lg dark:border-blue-400 dark:bg-slate-800 dark:text-slate-100">
|
||||||
{name (active).text}</div>}
|
{name (active).text}</div>}
|
||||||
</DragOverlay>, document.body)}
|
</DragOverlay>, document.body)}
|
||||||
</DndContext>
|
</DndContext>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ export const startAPIDownload = (
|
|||||||
): (() => void) => {
|
): (() => void) => {
|
||||||
const frame = document.createElement ('iframe')
|
const frame = document.createElement ('iframe')
|
||||||
frame.hidden = true
|
frame.hidden = true
|
||||||
let timer: ReturnType<typeof window.setTimeout> | null = null
|
let timer: number | null = null
|
||||||
let closed = false
|
let closed = false
|
||||||
const release = () => {
|
const release = () => {
|
||||||
if (closed) return
|
if (closed) return
|
||||||
|
|||||||
@@ -21,21 +21,18 @@ import { countsErrorMessage, countsExportLabels } from '@/lib/countsDisplay'
|
|||||||
import { isApiError } from '@/lib/api'
|
import { isApiError } from '@/lib/api'
|
||||||
import { CountsDefinitionContext, countsAxisFields, countsAxisLabel,
|
import { CountsDefinitionContext, countsAxisFields, countsAxisLabel,
|
||||||
visibleCountsResources, countsFieldLabel,
|
visibleCountsResources, countsFieldLabel,
|
||||||
fetchCountsDefinition }
|
fetchCountsDefinition } from '@/lib/countsDefinitions'
|
||||||
from '@/lib/countsDefinitions'
|
|
||||||
import { countsKeys } from '@/lib/queryKeys'
|
import { countsKeys } from '@/lib/queryKeys'
|
||||||
|
import { setCountState, readCountState } from '@/lib/queryState'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { useClientMotion } from '@/lib/useClientMotion'
|
import { useClientMotion } from '@/lib/useClientMotion'
|
||||||
import useDialogue from '@/lib/dialogues/useDialogue'
|
import useDialogue from '@/lib/dialogues/useDialogue'
|
||||||
import { useLocale } from '@/lib/useLocale'
|
import { useLocale } from '@/lib/useLocale'
|
||||||
import { useUITranslation } from '@/lib/useUITranslation'
|
import { useUITranslation } from '@/lib/useUITranslation'
|
||||||
|
|
||||||
import { setCountState, readCountState } from '@/lib/queryState'
|
import type { CountField, CountsResource } from '@/lib/counts'
|
||||||
|
|
||||||
import type { CountsAxis, CountsDefinition } from '@/lib/countsDefinitions'
|
import type { CountsAxis, CountsDefinition } from '@/lib/countsDefinitions'
|
||||||
|
|
||||||
import type { CountsResource } from '@/lib/counts'
|
|
||||||
|
|
||||||
type PendingCountsRun = {
|
type PendingCountsRun = {
|
||||||
key: ReturnType<typeof countsKeys.index>
|
key: ReturnType<typeof countsKeys.index>
|
||||||
origin: string
|
origin: string
|
||||||
@@ -44,7 +41,8 @@ type PendingCountsRun = {
|
|||||||
|
|
||||||
|
|
||||||
const tooManyColumns = (failure: unknown): number | null => {
|
const tooManyColumns = (failure: unknown): number | null => {
|
||||||
if (!isApiError (failure) || failure.response?.status !== 422) return null
|
if (!isApiError (failure) || failure.response?.status !== 422)
|
||||||
|
return null
|
||||||
const body = (failure.response.data ?? { }) as {
|
const body = (failure.response.data ?? { }) as {
|
||||||
error?: unknown; maxColumns?: unknown; max_columns?: unknown }
|
error?: unknown; maxColumns?: unknown; max_columns?: unknown }
|
||||||
const maximum = body.maxColumns ?? body.max_columns
|
const maximum = body.maxColumns ?? body.max_columns
|
||||||
@@ -251,7 +249,9 @@ const CountsResourceContent = (
|
|||||||
setParams (next)
|
setParams (next)
|
||||||
}
|
}
|
||||||
const download = async (format: 'csv' | 'json') => {
|
const download = async (format: 'csv' | 'json') => {
|
||||||
if (exportInFlight.current || pendingRun.current != null || definition == null) return
|
if (exportInFlight.current || pendingRun.current != null || definition == null)
|
||||||
|
return
|
||||||
|
|
||||||
exportInFlight.current = true
|
exportInFlight.current = true
|
||||||
setExporting (true)
|
setExporting (true)
|
||||||
setExportError (false)
|
setExportError (false)
|
||||||
@@ -259,7 +259,7 @@ const CountsResourceContent = (
|
|||||||
{
|
{
|
||||||
const axes = [...readCountState<CountsAxis[]> (params, 'rows', []),
|
const axes = [...readCountState<CountsAxis[]> (params, 'rows', []),
|
||||||
...readCountState<CountsAxis[]> (params, 'cols', [])]
|
...readCountState<CountsAxis[]> (params, 'cols', [])]
|
||||||
const fields = mode === 'summary' ? [
|
const fields: CountField[] = mode === 'summary' ? [
|
||||||
...axes.map (axis => ({
|
...axes.map (axis => ({
|
||||||
key: axis.field, label: countsFieldLabel (axis.field) })),
|
key: axis.field, label: countsFieldLabel (axis.field) })),
|
||||||
{ key: 'count', label: 'count' }]
|
{ key: 'count', label: 'count' }]
|
||||||
|
|||||||
新しいイシューから参照
ユーザーをブロックする