David Pomerenke
Translation both from and to
731eddd
raw
history blame
6.89 kB
import { DataTable } from 'primereact/datatable'
import { Column } from 'primereact/column'
import { FilterMatchMode } from 'primereact/api'
import { MultiSelect } from 'primereact/multiselect'
import { useState, useEffect } from 'react'
import { Slider } from 'primereact/slider'
import ScoreField from './ScoreField'
const LanguageTable = ({ data, selectedLanguages, setSelectedLanguages }) => {
const [filters, setFilters] = useState({
language_name: { value: null, matchMode: FilterMatchMode.EQUALS }, // via global search
family: { value: null, matchMode: FilterMatchMode.IN },
speakers: { value: null, matchMode: FilterMatchMode.BETWEEN }
})
const families = [...new Set(data.map(item => item.family))].slice(0, 10)
families.push("Other")
const familyRowFilterTemplate = options => {
return (
<MultiSelect
value={options.value}
options={families}
onChange={e => {
options.filterApplyCallback(e.value)
setFilters(prevFilters => ({
...prevFilters,
family: { value: e.value, matchMode: FilterMatchMode.IN }
}))
}}
placeholder='All families'
/>
)
}
const formatPopulation = population => {
if (population === null) {
return ''
} else if (population < 1000) {
return population.toFixed(0) + ''
} else if (population < 10 * 1000) {
return (population / 1000).toFixed(1) + 'K'
} else if (population < 1000 * 1000) {
return (population / 1000).toFixed(0) + 'K'
} else if (population < 10 * 1000 * 1000) {
return (population / 1000 / 1000).toFixed(1) + 'M'
}else if (population < 1000 * 1000 * 1000) {
return (population / 1000 / 1000).toFixed(0) + 'M'
} else {
return (population / 1000 / 1000 / 1000).toFixed(1) + 'B'
}
}
const SliderWithLabel = ({ value, onChange }) => {
const p = 10
const min = 4
const max = 9.3
const start = value === null ? min : Math.log(value[0]) / Math.log(p)
const stop = value === null ? max : Math.log(value[1]) / Math.log(p)
const [_value, _setValue] = useState([start, stop])
useEffect(() => {
const timer = setTimeout(() => {
onChange({
value:
_value[0] <= min + 0.1 && _value[1] >= max - 0.1
? null
: [p ** _value[0], p ** _value[1]]
})
}, 1000)
return () => clearTimeout(timer)
}, [_value, onChange])
return (
<div style={{ minWidth: '20rem' }}>
<div>{formatPopulation(p ** _value[0])}</div>
<div>{formatPopulation(p ** _value[1])}</div>
<Slider
value={_value}
onChange={e => _setValue(e.value)}
placeholder='All sizes'
min={min}
max={max}
step={0.01}
range
style={{ marginTop: '5rem' }}
/>
</div>
)
}
const speakerFilterTemplate = options => {
return (
<SliderWithLabel
value={options.value}
onChange={e => {
options.filterApplyCallback(e.value)
setFilters(prevFilters => ({
...prevFilters,
speakers: { value: e.value, matchMode: FilterMatchMode.BETWEEN }
}))
}}
/>
)
}
const speakerBodyTemplate = rowData => {
const populationStr = formatPopulation(rowData.speakers)
return <div style={{ textAlign: 'center' }}>{populationStr}</div>
}
const languageBodyTemplate = rowData => {
return <div>
<div style={{ fontWeight: 'bold' }}>{rowData.autonym}</div>
<div style={{ fontSize: '0.8rem', color: 'gray' }}>{rowData.language_name}</div>
</div>
}
const scoreBodyTemplate = (field, options = {}) => {
const { minScore = 0, maxScore = 1 } = options
return rowData => {
const score = rowData[field]
return ScoreField(score, minScore, maxScore)
}
}
return (
<DataTable
value={data.filter(item => !selectedLanguages.some(l => l.bcp_47 === item.bcp_47))}
header={<>Languages</>}
sortField='speakers'
removableSort
filters={filters}
filterDisplay='menu'
selectionMode='checkbox'
selection={selectedLanguages}
onSelectionChange={e => setSelectedLanguages(e.value)}
frozenValue={selectedLanguages}
virtualScrollerOptions={{ itemSize: 60 }}
scrollable
scrollHeight='600px'
id='language-table'
style={{ width: '800px', minHeight: '650px' }}
>
<Column selectionMode="multiple" headerStyle={{ width: '3rem' }} />
<Column
field='language_name'
header='Language'
body={languageBodyTemplate}
style={{ minWidth: '10rem' }}
frozen
/>
<Column
field='speakers'
header={<i className='pi pi-users' title='Speakers' />}
body={speakerBodyTemplate}
filter
filterElement={speakerFilterTemplate}
showFilterMatchModes={false}
sortable
style={{ minWidth: '5rem' }}
/>
<Column
field='family'
header='Family'
filter
showFilterMatchModes={false}
filterElement={familyRowFilterTemplate}
style={{ minWidth: '10rem' }}
/>
<Column
field='average'
header='Average'
sortable
body={scoreBodyTemplate('average', { minScore: 0.2, maxScore: 0.5 })}
style={{ minWidth: '5rem', maxWidth: '10rem' }}
/>
<Column
field='translation_from_bleu'
header="Translation (from)"
headerTooltip='Translation performance from a language to all other languages (spBLEU score)'
sortable
body={scoreBodyTemplate('translation_from_bleu', {
minScore: 0,
maxScore: 0.5
})}
style={{ minWidth: '5rem', maxWidth: '10rem' }}
/>
<Column
field='translation_to_bleu'
header="Translation (to)"
headerTooltip='Translation performance from all other languages to a language (spBLEU score)'
sortable
body={scoreBodyTemplate('translation_to_bleu', {
minScore: 0,
maxScore: 0.5
})}
style={{ minWidth: '5rem', maxWidth: '10rem' }}
/>
<Column
field='classification_accuracy'
header='Classification'
sortable
body={scoreBodyTemplate('classification_accuracy', {
minScore: 0,
maxScore: 0.5
})}
style={{ minWidth: '5rem', maxWidth: '10rem' }}
/>
{/* <Column
field='language_modeling_chrf'
header='Language Modeling'
sortable
body={scoreBodyTemplate('language_modeling_chrf', {
minScore: 0.8,
maxScore: 1
})}
style={{ minWidth: '5rem', maxWidth: '10rem' }}
/> */}
</DataTable>
)
}
export default LanguageTable