このコミットが含まれているのは:
2026-10-28 00:28:29 +09:00
コミット d6cf992622
27個のファイルの変更、630行の追加、60行の削除
+30 -2
ファイルの表示
@@ -8,7 +8,8 @@ import type { CountField, CountsResource } from '@/lib/counts'
export type CountsAxis = { field: string; grain?: string }
export type CountsCondition = {
field: string; operator: string; value?: string; end?: string; blank?: boolean }
field: string; operator: string; value?: string; end?: string; blank?: boolean
input?: 'single' | 'multiple' | 'list'; values?: (string | number | boolean)[] }
export type CountsFieldType = 'string' | 'integer' | 'datetime' | 'enum'
| 'json' | 'boolean' | 'interval'
@@ -22,7 +23,9 @@ export const visibleCountsResources = [
export type CountsFieldMetadata = {
key: string; type: CountsFieldType; nullable: boolean; operators: string[]
labels?: string[]; multiple?: boolean }
labels?: string[]; multiple?: boolean; candidateSource?: 'categories' | 'tags'
setType?: 'tag_reference'; inputTypes?: string[]
choices?: { value: string; label: string }[] }
export type CountsDefinition = {
fields: CountsFieldMetadata[]
outputFields?: CountField[]
@@ -44,6 +47,31 @@ export const useCountsDefinition = (): CountsDefinition => {
export const fetchCountsDefinition = (resource: CountsResource): Promise<CountsDefinition> =>
apiGet (`/counts/definitions/${encodeURIComponent (resource)}`)
export type CountsCandidate = {
value: string; id?: number; name: string | null; category?: string | null
kind?: 'internal' | 'external' }
export type CountsCandidatesResult = {
rows: CountsCandidate[]; page: number; more: boolean; executionAt: string }
export const fetchCountsCandidates = (
params: URLSearchParams,
locale: LocaleCode,
signal?: AbortSignal,
): Promise<CountsCandidatesResult> => apiGet (
'/counts/definitions/posts/candidates', {
params: Object.fromEntries (params), locale, signal })
export const countsSetOperators = ['in', 'not_in', 'any', 'all', 'none']
export const countsConditionInputs = (
field: CountsFieldMetadata | undefined,
operator: string,
): ('single' | 'multiple' | 'list')[] => {
if (!countsSetOperators.includes (operator)) return ['single']
if (field?.candidateSource === 'tags') return ['list']
return field?.candidateSource == null ? ['multiple'] : ['list', 'multiple']
}
export const countsFilterFields = (
definition: CountsDefinition,