このコミットが含まれているのは:
+54
-24
@@ -1,6 +1,8 @@
|
||||
import { countsFieldLabel, readCountsJSON } from '@/lib/countsDefinitions'
|
||||
import { countsFieldLabel } from '@/lib/countsDefinitions'
|
||||
import { apiDownload, apiGet } from '@/lib/api'
|
||||
|
||||
import { readCountState, encodeCountState } from '@/lib/queryState'
|
||||
|
||||
import type { CountsAxis, CountsDefinition } from '@/lib/countsDefinitions'
|
||||
import type { LocaleCode } from '@/lib/locales'
|
||||
import type { TagNameSnapshot } from '@/types'
|
||||
@@ -58,6 +60,8 @@ export type CountsStateTotals = {
|
||||
export type CountsPivotHeader = { values: (string | number | null)[]
|
||||
kind: 'data' | 'subtotal' | 'grand_total' }
|
||||
export type CountsResult = {
|
||||
populationCount?: number
|
||||
populationCountScope?: string
|
||||
rowHeaders?: CountsPivotHeader[]
|
||||
columnHeaders?: CountsPivotHeader[]
|
||||
pivotTotals?: { row: (string | number | null)[]; column: (string | number | null)[]
|
||||
@@ -95,7 +99,7 @@ export const countColumns: Record<string, string> = {
|
||||
parents: 'shared:labels.parentPosts', video_ms: 'shared:labels.duration',
|
||||
original_created_from: 'counts:columns.originalFrom',
|
||||
original_created_before: 'counts:columns.originalBefore',
|
||||
name: 'history:tagName', names: 'counts:columns.names',
|
||||
name: 'counts:columns.name', names: 'counts:columns.names',
|
||||
category: 'common:categoryLabel', aliases: 'tags:aliases',
|
||||
deprecated: 'counts:columns.deprecated', user: 'history:actor',
|
||||
created_at: 'counts:columns.changedAt' }
|
||||
@@ -165,7 +169,9 @@ export const fieldsForCounts = (
|
||||
key,
|
||||
label: (key === 'parents' && resource === 'tags') ? 'tags:parents'
|
||||
: (countColumns[key] ?? countsFieldLabel (key)),
|
||||
children: nested[key] }))
|
||||
children: key === 'parents' && resource === 'tags'
|
||||
? [...(nested.parents ?? []), { key: 'name', label: 'counts:columns.name' }]
|
||||
: nested[key] }))
|
||||
|
||||
|
||||
export const orderedCountFields = (
|
||||
@@ -174,7 +180,7 @@ export const orderedCountFields = (
|
||||
parent = '',
|
||||
): CountField[] => {
|
||||
const prefix = parent ? `${parent}.` : ''
|
||||
const saved = (params.get ('order') ?? '').split (',')
|
||||
const saved = (params.get ('order') ?? '').split (' ')
|
||||
const keys = [...new Set ([...saved, ...fields.map (field => `${prefix}${field.key}`)])]
|
||||
const ordered = keys.flatMap (key => {
|
||||
const field = fields.find (field => `${prefix}${field.key}` === key)
|
||||
@@ -201,8 +207,8 @@ export const reorderCountFields = (
|
||||
const current = ordered.map (field => `${prefix}${field.key}`)
|
||||
const next = [...current]
|
||||
next.splice (last, 0, ...next.splice (first, 1))
|
||||
return [...(params.get ('order') ?? '').split (',').filter (
|
||||
key => key && !current.includes (key)), ...next].join (',')
|
||||
return [...(params.get ('order') ?? '').split (' ').filter (
|
||||
key => key && !current.includes (key)), ...next].join (' ')
|
||||
}
|
||||
|
||||
|
||||
@@ -220,7 +226,7 @@ export const selectedCountColumns = (
|
||||
tag_descriptions: ['language_code', 'body', 'source_language_code'],
|
||||
tag_groups: ['name', 'description', 'members'],
|
||||
materials: ['url', 'source_kind', 'tag_id'] }
|
||||
const selected = resolved.has ('columns') ? resolved.get ('columns')!.split (',')
|
||||
const selected = resolved.has ('columns') ? resolved.get ('columns')!.split (' ')
|
||||
: [...common, ...defaults[resource]]
|
||||
return orderedCountFields (fieldsForCounts (resource, definition), resolved)
|
||||
.map (field => field.key as CountColumn).filter (key => selected.includes (key))
|
||||
@@ -234,13 +240,26 @@ export const countChildPaths = (fields: CountField[], prefix = ''): string[] =>
|
||||
})
|
||||
|
||||
|
||||
export const selectedCountChildren = (params: URLSearchParams): Set<string> =>
|
||||
new Set (params.has ('children') ? params.get ('children')!.split (',')
|
||||
: ['tags.name', 'parents.id', 'aliases.name', 'members.tagId'])
|
||||
export const selectedCountChildren = (params: URLSearchParams): Set<string> => {
|
||||
const selected = new Set (params.has ('children') ? params.get ('children')!.split (' ')
|
||||
: ['tags.name', 'parents.id', 'aliases.name', 'members.tagId'])
|
||||
const clean = (fields: CountField[], prefix: string) => {
|
||||
for (const field of fields)
|
||||
{
|
||||
const path = `${prefix}.${field.key}`
|
||||
if (field.children == null) continue
|
||||
clean (field.children, path)
|
||||
if (!field.children.some (child => selected.has (`${path}.${child.key}`)))
|
||||
selected.delete (path)
|
||||
}
|
||||
}
|
||||
for (const [path, fields] of Object.entries (nested)) clean (fields ?? [], path)
|
||||
return selected
|
||||
}
|
||||
|
||||
|
||||
export const readCountSort = (value: string | null): CountSort[] =>
|
||||
(value ?? '').split (',').flatMap (entry => {
|
||||
(value ?? '').split (' ').flatMap (entry => {
|
||||
const [key, direction] = entry.split (':')
|
||||
return (key && (direction === 'asc' || direction === 'desc'))
|
||||
? [{ key, direction }] : []
|
||||
@@ -248,7 +267,7 @@ export const readCountSort = (value: string | null): CountSort[] =>
|
||||
|
||||
|
||||
export const writeCountSort = (sort: CountSort[]): string =>
|
||||
sort.map (item => `${item.key}:${item.direction}`).join (',')
|
||||
sort.map (item => `${item.key}:${item.direction}`).join (' ')
|
||||
|
||||
|
||||
export const changeCountSort = (
|
||||
@@ -274,7 +293,7 @@ export const selectedCountFields = (
|
||||
parent = '',
|
||||
): CountField[] => {
|
||||
const selected = params.has (selectionKey)
|
||||
? new Set (params.get (selectionKey)!.split (',')) : null
|
||||
? new Set (params.get (selectionKey)!.split (' ')) : null
|
||||
return orderedCountFields (fields, params, parent)
|
||||
.filter (field => selected == null || selected.has (field.key))
|
||||
}
|
||||
@@ -300,7 +319,7 @@ export const normaliseCountsParams = (
|
||||
if (!params.has ('rows') && params.has ('axis'))
|
||||
{
|
||||
const field = params.get ('axis') === 'month' ? 'created_at' : params.get ('axis')!
|
||||
params.set ('rows', JSON.stringify ([{
|
||||
params.set ('rows', encodeCountState ('rows', [{
|
||||
field, ...(field === 'created_at' ? { grain: 'month' } : { }) }]))
|
||||
}
|
||||
if (params.has ('before') && !params.has ('through'))
|
||||
@@ -309,16 +328,16 @@ export const normaliseCountsParams = (
|
||||
params.delete (key)
|
||||
if (params.has ('columns') && ['posts', 'tags'].includes (resource))
|
||||
{
|
||||
const selected = new Set (params.get ('columns')!.split (','))
|
||||
const selected = new Set (params.get ('columns')!.split (' '))
|
||||
params.set ('columns', columnsForCounts (resource).filter (key => selected.has (key))
|
||||
.join (','))
|
||||
.join (' '))
|
||||
}
|
||||
if (params.has ('sort'))
|
||||
params.set ('sort', params.get ('sort')!.split (',')
|
||||
.filter (entry => entry.split (':')[0] !== 'original_created_at').join (','))
|
||||
params.set ('sort', params.get ('sort')!.split (' ')
|
||||
.filter (entry => entry.split (':')[0] !== 'original_created_at').join (' '))
|
||||
if (params.has ('order'))
|
||||
params.set ('order', params.get ('order')!.split (',')
|
||||
.filter (key => key !== 'original_created_at').join (','))
|
||||
params.set ('order', params.get ('order')!.split (' ')
|
||||
.filter (key => key !== 'original_created_at').join (' '))
|
||||
const defaults = definition?.defaults?.find (entry =>
|
||||
entry.definition === params.get ('definition') && entry.mode === params.get ('mode'))
|
||||
for (const { key, value } of defaults?.params ?? [])
|
||||
@@ -327,13 +346,24 @@ export const normaliseCountsParams = (
|
||||
if (key === 'sort')
|
||||
{
|
||||
const expected = defaults?.params.find (entry => entry.key === 'rows')?.value
|
||||
const axes = readCountsJSON<CountsAxis[]> (params, 'rows', [])
|
||||
const first = expected == null ? null : (JSON.parse (expected) as CountsAxis[])[0]
|
||||
const axes = readCountState<CountsAxis[]> (params, 'rows', [])
|
||||
const first = expected == null ? null : readCountState<CountsAxis[]> (new URLSearchParams ({ rows: expected }), 'rows', [])[0]
|
||||
if (!Array.isArray (axes) || axes[0]?.field !== first?.field
|
||||
|| (axes[0]?.grain ?? 'month') !== (first?.grain ?? 'month')) continue
|
||||
}
|
||||
params.set (key, value)
|
||||
}
|
||||
const children = selectedCountChildren (params)
|
||||
if (params.has ('children')) params.set ('children', [...children].filter (Boolean).join (' '))
|
||||
if (params.has ('columns'))
|
||||
{
|
||||
const fields = fieldsForCounts (resource, definition)
|
||||
params.set ('columns', params.get ('columns')!.split (' ').filter (key => {
|
||||
const field = fields.find (field => field.key === key)
|
||||
return field != null && (field.children == null
|
||||
|| field.children.some (child => children.has (`${key}.${child.key}`)))
|
||||
}).join (' '))
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
@@ -393,13 +423,13 @@ export const countsExportPayload = (
|
||||
{
|
||||
const selected = selectedCountChildren (params)
|
||||
payload.set ('children', countChildPaths (fieldsForCounts (resource, definition))
|
||||
.filter (path => selected.has (path)).join (','))
|
||||
.filter (path => selected.has (path)).join (' '))
|
||||
}
|
||||
payload.delete ('current')
|
||||
payload.delete ('row_numbers')
|
||||
if (isCountsState (params) && countsUseLatest (params)) payload.delete ('at')
|
||||
return { ...Object.fromEntries (payload), resource, format,
|
||||
columns: columns.join (','), headers: JSON.stringify (headers),
|
||||
columns: columns.join (' '), headers: JSON.stringify (headers),
|
||||
labels: JSON.stringify (labels) }
|
||||
}
|
||||
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする