このコミットが含まれているのは:
2026-10-25 22:16:20 +09:00
コミット 96a5bb8601
12個のファイルの変更、600行の追加、25行の削除
+39 -4
ファイルの表示
@@ -36,13 +36,35 @@ export type CountsVersion = {
category?: string
aliases?: { languageCode: string; name: string; scriptCode: string }[]
deprecated?: string | null }
export type CountsStateRow = {
kind: 'internal' | 'external'
tagId: number
name: string | null
deprecated?: string | null
period?: string
at: string
count: number | null }
export type CountsStateTotals = {
posts: number | null
tags: number | null
assignments: number | null
deprecatedTags: number | null
externalAssignments: number | null }
export type CountsResult = {
count: number
page: number
limit: number
groupCount?: number
groups?: { key: string | number | null; name: string | null; count: number }[]
versions?: CountsVersion[] }
versions?: CountsVersion[]
at?: string
from?: string
before?: string
grain?: string
totals?: CountsStateTotals
stateRows?: CountsStateRow[]
coverage?: { basis: string; exact: boolean
postHistoryFrom: string | null; tagHistoryFrom: string | null } }
export type CountSort = { key: string; direction: 'asc' | 'desc' }
export type CountField = { key: string; label: string; children?: CountField[] }
export type CountRecord = Record<string, unknown>
@@ -200,6 +222,8 @@ export const normaliseCountsParams = (
): URLSearchParams => {
const params = new URLSearchParams (source)
params.delete ('event_type')
if (!params.has ('mode'))
params.set ('mode', source.has ('axis') ? 'summary' : 'state')
if (!['month', 'user'].includes (params.get ('axis') ?? ''))
params.set ('axis', 'month')
if (params.has ('columns'))
@@ -212,9 +236,18 @@ export const normaliseCountsParams = (
}
export const isCountsState = (params: URLSearchParams): boolean =>
['state', 'trend', 'snapshot'].includes (params.get ('mode') ?? 'state')
export const countsRequestParams = (params: URLSearchParams): URLSearchParams => {
const result = new URLSearchParams (params)
for (const key of ['columns', 'children', 'child_sort', 'nested_json', 'order'])
const hidden = isCountsState (params)
? ['axis', 'latest', 'user_id', 'resource_id']
: ['at', 'grain', 'kind']
if (isCountsState (params) && params.get ('mode') !== 'trend')
hidden.push ('from', 'before')
for (const key of ['columns', 'children', 'child_sort', 'nested_json', 'order', ...hidden])
result.delete (key)
return result
}
@@ -224,8 +257,10 @@ export const fetchCounts = (
resource: CountsResource,
params: URLSearchParams,
locale: LocaleCode,
): Promise<CountsResult> => apiGet (`/counts/${resource}`, {
locale, params: Object.fromEntries (countsRequestParams (params)) })
): Promise<CountsResult> => apiGet (isCountsState (params) ? '/counts/state' : `/counts/${resource}`, {
locale, params: { ...Object.fromEntries (countsRequestParams (params)),
...(isCountsState (params) ? { resource } : { }) } })
const stableValue = (value: unknown): unknown => {
+52
ファイルの表示
@@ -0,0 +1,52 @@
import { translateUIMessage } from '@/lib/i18n'
import type { CountField, CountsStateRow } from '@/lib/counts'
import type { LocaleCode } from '@/lib/locales'
export const countsStateFields = (trend: boolean): CountField[] => trend
? [{ key: 'period', label: 'counts:state.period' },
{ key: 'count', label: 'counts:state.postCount' }]
: [{ key: 'kind', label: 'counts:columns.kind' },
{ key: 'tag_id', label: 'counts:columns.resourceId' },
{ key: 'name', label: 'history:tagName' },
{ key: 'deprecated', label: 'counts:columns.deprecated' },
{ key: 'count', label: 'counts:state.postCount' }]
export const countsStateCell = (
row: CountsStateRow,
key: string,
locale: LocaleCode,
): string => {
switch (key)
{
case 'period': return row.period ?? ''
case 'count': return row.count == null ? '—' : String (row.count)
case 'tag_id': return String (row.tagId)
case 'kind': return translateUIMessage (`kinds.${row.kind}`, 'counts', locale).text
case 'name': return row.name ?? translateUIMessage ('notRegistered', 'counts', locale).text
case 'deprecated': return row.deprecated
? translateUIMessage ('common:states.deprecated', 'counts', locale).text : ''
default: return ''
}
}
export const countsStateDrill = (
params: URLSearchParams,
at: string,
resource = 'posts',
row?: CountsStateRow,
): string => {
const next = new URLSearchParams (params)
for (const key of ['sort', 'page', 'tag', 'from', 'before']) next.delete (key)
next.set ('mode', 'snapshot')
next.set ('at', at)
if (row != null)
{
next.set ('kind', row.kind)
next.set ('tag', String (row.tagId))
}
return `/counts/${resource}?${next}`
}
+1 -1
ファイルの表示
@@ -9,7 +9,7 @@ export const defaultCountWidths: Record<string, number> = {
video_ms: 120, original_created_at: 260, original_created_from: 240,
original_created_before: 240, name: 240, names: 480, category: 180,
aliases: 360, deprecated: 240, user: 200, created_at: 240, group: 240, count: 160,
id: 88, versionNo: 88, kind: 140, sections: 260,
period: 200, tag_id: 88, id: 88, versionNo: 88, kind: 140, sections: 260,
languageCode: 180, scriptCode: 200, autoGenerated: 120 }
type Layout = {