このコミットが含まれているのは:
@@ -22,7 +22,9 @@ const ConditionEditor = (
|
||||
save: (condition: CountsCondition) => void },
|
||||
) => {
|
||||
const { label, message } = useUITranslation ('counts')
|
||||
const fields = countsFilterFields (definition)
|
||||
const fields = definition.filterFields ?? definition.fields
|
||||
const fieldName = (key: string) => (fields.find (item => item.key === key)?.labels
|
||||
?? [countsFieldLabel (key)]).map (key => message (key).text).join (' › ')
|
||||
const [condition, setCondition] = useState<CountsCondition> (() => {
|
||||
const next = { ...initial, field: initial?.field ?? 'resource_id',
|
||||
operator: initial?.operator ?? 'eq' }
|
||||
@@ -30,7 +32,7 @@ const ConditionEditor = (
|
||||
return next
|
||||
})
|
||||
const { field, operator } = condition
|
||||
const operators = definition.fields.find (item => item.key === field)?.operators ?? []
|
||||
const operators = fields.find (item => item.key === field)?.operators ?? []
|
||||
useEffect (() => {
|
||||
controls.setActions ([{ label: label (initial == null ? 'add' : 'shared:actions.edit'),
|
||||
onSelect: () => save (condition) }])
|
||||
@@ -39,11 +41,11 @@ const ConditionEditor = (
|
||||
<select value={field} aria-label={message ('field').text} className={inputClass ()}
|
||||
onChange={event => {
|
||||
const field = event.target.value
|
||||
const operator = definition.fields.find (item => item.key === field)?.operators[0]
|
||||
const operator = fields.find (item => item.key === field)?.operators[0]
|
||||
if (operator != null) setCondition ({ field, operator })
|
||||
}}>
|
||||
{Object.keys (fields).filter (key => fields[key] !== 'json').map (key => (
|
||||
<option key={key} value={key}>{message (countsFieldLabel (key)).text}</option>))}
|
||||
{fields.filter (field => field.operators.length > 0).map (field => (
|
||||
<option key={field.key} value={field.key}>{fieldName (field.key)}</option>))}
|
||||
</select>
|
||||
<select value={operator} aria-label={message ('operator').text} className={inputClass ()}
|
||||
onChange={event => setCondition (previous => {
|
||||
@@ -68,6 +70,9 @@ const CountsAdditionalConditions = ({ params, update }: {
|
||||
const definition = useCountsDefinition ()
|
||||
const dialogue = useDialogue ()
|
||||
const conditions = readCountState<CountsCondition[]> (params, 'conditions', [])
|
||||
const metadata = definition.filterFields ?? definition.fields
|
||||
const fieldName = (key: string) => (metadata.find (item => item.key === key)?.labels
|
||||
?? [countsFieldLabel (key)]).map (key => message (key).text).join (' › ')
|
||||
const write = (next: CountsCondition[]) => update ('conditions', encodeCountState ('conditions', next))
|
||||
const edit = (index?: number) => {
|
||||
const initial = index == null ? undefined : conditions[index]
|
||||
@@ -81,37 +86,45 @@ const CountsAdditionalConditions = ({ params, update }: {
|
||||
}
|
||||
const patch = (index: number, change: Partial<CountsCondition>) => write (
|
||||
conditions.map ((item, position) => position === index ? { ...item, ...change } : item))
|
||||
const valueInput = (condition: CountsCondition, index: number, key: 'value' | 'end') => {
|
||||
const type = countsFilterFields (definition)[condition.field]
|
||||
const aria = message (key === 'end' ? 'through' : 'value')
|
||||
if (type === 'boolean' || condition.field === 'event_type')
|
||||
{
|
||||
const options: string[] = type === 'boolean' ? ['true', 'false'] : [...countsEventTypes]
|
||||
const namespace = type === 'boolean' ? 'truthValues' : 'events'
|
||||
return <select key={key} value={condition[key] ?? ''} disabled={condition.blank}
|
||||
className={inputClass (false, 'w-36 py-1')} aria-label={aria.text}
|
||||
onChange={event => patch (index, { [key]: event.target.value })}>
|
||||
<option value=""/>
|
||||
{options.map (value => <option key={value} value={value}
|
||||
lang={message (`${namespace}.${value}`).language}>
|
||||
{message (`${namespace}.${value}`).text}</option>)}
|
||||
</select>
|
||||
}
|
||||
if (type === 'datetime')
|
||||
return <DateTimeField precision="second" key={key}
|
||||
value={condition[key] ?? ''} disabled={condition.blank}
|
||||
aria-label={aria.text} lang={aria.language}
|
||||
onChange={value => patch (index, { [key]: value ?? '' })}/>
|
||||
return <input key={key} value={condition[key] ?? ''} disabled={condition.blank}
|
||||
type={(type === 'integer' || type === 'interval') ? 'number' : 'text'}
|
||||
className={inputClass (false, 'w-36 py-1')}
|
||||
aria-label={aria.text} lang={aria.language}
|
||||
onChange={event => patch (index, { [key]: event.target.value })}/>
|
||||
}
|
||||
return <fieldset className="space-y-1">
|
||||
<legend className="flex items-center gap-2">{label ('additionalConditions')}
|
||||
<Button type="button" variant="outline" size="sm" onClick={() => edit ()}>
|
||||
{label ('add')}</Button></legend>
|
||||
{conditions.map ((condition, index) => {
|
||||
const datetime = countsFilterFields (definition)[condition.field] === 'datetime'
|
||||
return <div key={index} className="flex flex-wrap items-center gap-1">
|
||||
<button type="button" onClick={() => edit (index)}>
|
||||
{label (countsFieldLabel (condition.field))}
|
||||
{fieldName (condition.field)}
|
||||
{' · '}{label (`operators.${condition.operator}`)}
|
||||
</button>
|
||||
{(condition.operator === 'range' ? ['value', 'end'] as const : ['value'] as const)
|
||||
.map (key => condition.field === 'event_type' ? (
|
||||
<select key={key} value={condition[key] ?? ''} disabled={condition.blank}
|
||||
className={inputClass (false, 'w-36 py-1')}
|
||||
aria-label={message ('value').text}
|
||||
onChange={event => patch (index, { [key]: event.target.value })}>
|
||||
<option value=""/>
|
||||
{condition[key] && !countsEventTypes.some (event => event === condition[key])
|
||||
&& <option value={condition[key]}>{condition[key]}</option>}
|
||||
{countsEventTypes.map (event => <option key={event} value={event}
|
||||
lang={message (`events.${event}`).language}>
|
||||
{message (`events.${event}`).text}</option>)}
|
||||
</select>) : (datetime ? <DateTimeField precision="second" key={key}
|
||||
value={condition[key] ?? ''} disabled={condition.blank}
|
||||
aria-label={message (key === 'end' ? 'through' : 'value').text}
|
||||
onChange={value => patch (index, { [key]: value ?? '' })}/> : (
|
||||
<input key={key} value={condition[key] ?? ''} disabled={condition.blank}
|
||||
className={inputClass (false, 'w-36 py-1')}
|
||||
aria-label={message ('value').text}
|
||||
onChange={event => patch (index, { [key]: event.target.value })}/>)))}
|
||||
.map (key => valueInput (condition, index, key))}
|
||||
<label className="inline-flex items-center gap-1">
|
||||
<input type="checkbox" checked={condition.blank ?? false}
|
||||
onChange={event => patch (index, { blank: event.target.checked })}/>
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする