このコミットが含まれているのは:
2026-10-28 00:28:29 +09:00
コミット d6cf992622
27個のファイルの変更、630行の追加、60行の削除
+37 -8
ファイルの表示
@@ -1,7 +1,8 @@
// Public URL grammar: space-delimited tokens and indexed scalar fields, never JSON.
export type QueryRecord = Record<string, string | number | boolean | null | undefined>
const schemas: Record<string, string[]> = {
conditions: ['field', 'operator', 'value', 'end', 'blank'],
conditions: ['field', 'operator', 'value', 'end', 'blank', 'input', 'values'],
condition_values: ['condition', 'value', 'value_type'],
drill: ['field', 'grain', 'value', 'value_type'],
tag_refs: ['name', 'tag_id', 'external_tag_id', 'negative', 'missing'],
column_order: ['value', 'value_type'],
@@ -23,8 +24,8 @@ export const queryRecords = (params: URLSearchParams, key: string): QueryRecord[
const index = Number (parts[0])
const record = indexed.get (index) ?? { }
const field = parts[1]
record[field] = ['blank', 'negative', 'missing'].includes (field)
? value === '1' : (['tag_id', 'external_tag_id', 'axis'].includes (field)
record[field] = ['blank', 'negative', 'missing', 'values'].includes (field)
? value === '1' : (['tag_id', 'external_tag_id', 'axis', 'condition'].includes (field)
? Number (value) : value)
indexed.set (index, record)
}
@@ -52,11 +53,13 @@ export const setQueryRecords = (
if (value == null && field !== 'value') continue
if (!schemas[key]?.includes (field)) continue
const name = `${key}.${index}.${field}`
if (field === 'value' && ['drill', 'measures', 'column_order'].includes (key))
if (field === 'value'
&& ['drill', 'measures', 'column_order', 'condition_values'].includes (key))
params.set (`${key}.${index}.value_type`, value == null ? 'null' : typeof value)
if (value == null) continue
params.set (name, typeof value === 'boolean'
? (['blank', 'negative', 'missing'].includes (field) ? (value ? '1' : '0') : String (value))
? (['blank', 'negative', 'missing', 'values'].includes (field)
? (value ? '1' : '0') : String (value))
: String (value))
}
})
@@ -74,16 +77,34 @@ export const readCountState = <T,> (
const [field, grain] = token.split (':')
return grain == null ? { field } : { field, grain }
}) as T
return queryRecords (params, key) as T
const records = queryRecords (params, key)
if (key === 'conditions')
{
const values = queryRecords (params, 'condition_values')
return records.map ((record, index) => record.values === true
? { ...record, values: values.filter (entry => entry.condition === index)
.map (entry => entry.value) } : record) as T
}
return records as T
}
export const encodeCountState = (key: string, records: QueryRecord[]): string => {
export const encodeCountState = (key: string, records: Record<string, unknown>[]): string => {
if (key === 'rows' || key === 'cols')
return records.map (record => record.grain == null
? String (record.field) : `${record.field}:${record.grain}`).join (' ')
const params = new URLSearchParams ()
setQueryRecords (params, key, records)
const values: QueryRecord[] = []
const flat = records.map ((record, condition) => {
if (key !== 'conditions' || !Array.isArray (record.values)) return record as QueryRecord
const { values: selected, ...fields } = record
for (const value of selected as unknown[])
values.push ({ condition, value: value as string | number | boolean })
return { ...fields, values: true } as QueryRecord
})
setQueryRecords (params, key, flat)
if (key === 'conditions' && flat.some (record => record.values === true))
setQueryRecords (params, 'condition_values', values)
return params.toString ()
}
@@ -93,6 +114,14 @@ export const setCountState = (params: URLSearchParams, key: string, value: strin
{
const fields = new URLSearchParams (value)
setQueryRecords (params, key, queryRecords (fields, key))
if (key === 'conditions')
{
for (const name of [...params.keys ()])
if (name === 'condition_values' || name.startsWith ('condition_values.'))
params.delete (name)
if (fields.has ('condition_values'))
setQueryRecords (params, 'condition_values', queryRecords (fields, 'condition_values'))
}
}
else params.set (key, value)
}