<commit_before>import { Spinner } from '@blueprintjs/core'
import React, { FC, useEffect, useState } from 'react'

import { getLanguageSourceClient } from './api'
import { LanguageSource } from './typings'
import Language from './Language'

// TODO better typings
interface LanguageData {
  available: any[]
  downloading: any[]
  installed: any[]
}

const fetchLanguages = async (langSource: LanguageSource, setLanguages: Function) => {
  const client = getLanguageSourceClient(langSource)
  const { data } = (await client.get('/languages')) as { data: LanguageData }
  setLanguages(data)
}

interface Props {
  languageSource: LanguageSource
  readOnly: boolean
}

const LanguageManagement: FC<Props> = props => {
  const [languages, setLanguages] = useState<LanguageData | undefined>()
  useEffect(() => {
    const init = async () => {
      await fetchLanguages(props.languageSource, setLanguages)
    }

    init()
  }, [])

  // TODO extract this as a custom hook
  useEffect(() => {
    const id = setInterval(fetchLanguages.bind({}, props.languageSource!, setLanguages), 2000)
    return () => clearInterval(id)
  })

  if (!languages) {
    return <Spinner size={30} />
  }

  const downloadables = (languages.available || []).filter(
    lang => !languages.installed.find((l: any) => l.lang === lang.code)
  )

  const installed = languages.installed.map(x => ({
    ...x,
    ...languages.available.find(l => l.code === x.lang)
  }))

  return (
    <React.Fragment>
      {languages && languages.available.length > 0 && !props.readOnly && (
        <div className='languages-list'>
          {/* TODO add a select when we have too many languages */}
          <h4>Add Languages</h4>
          {downloadables.map(lang => (
            <Language
              key={lang.code}
              language={lang}
              installed={false}
              loaded={false}
              allowActions={!props.readOnly}
              languageSource={props.languageSource}
              downloadProgress={languages.downloading.find(l => l.lang == lang.code)}
            />
          ))}
        </div>
      )}
      <div className='languages-list'>
        <h4>Installed Languages</h4>
        {installed.length === 0 && <p>No languages yet</p>}
        {installed.map(lang => (
          <Language
            key={lang.code}
            language={lang}
            installed={true}
            loaded={lang.loaded}
            allowActions={!props.readOnly}
            languageSource={props.languageSource}
          />
        ))}
      </div>
    </React.Fragment>
  )
}

export default LanguageManagement
<commit_msg>fix(lang-server): hide add language if there is none available<commit_after>import { Spinner } from '@blueprintjs/core'
import React, { FC, useEffect, useState } from 'react'

import { getLanguageSourceClient } from './api'
import { LanguageSource } from './typings'
import Language from './Language'

// TODO better typings
interface LanguageData {
  available: any[]
  downloading: any[]
  installed: any[]
}

const fetchLanguages = async (langSource: LanguageSource, setLanguages: Function) => {
  const client = getLanguageSourceClient(langSource)
  const { data } = (await client.get('/languages')) as { data: LanguageData }
  setLanguages(data)
}

interface Props {
  languageSource: LanguageSource
  readOnly: boolean
}

const LanguageManagement: FC<Props> = props => {
  const [languages, setLanguages] = useState<LanguageData | undefined>()
  useEffect(() => {
    const init = async () => {
      await fetchLanguages(props.languageSource, setLanguages)
    }

    init()
  }, [])

  // TODO extract this as a custom hook
  useEffect(() => {
    const id = setInterval(fetchLanguages.bind({}, props.languageSource!, setLanguages), 2000)
    return () => clearInterval(id)
  })

  if (!languages) {
    return <Spinner size={30} />
  }

  const downloadables = (languages.available || []).filter(
    lang => !languages.installed.find((l: any) => l.lang === lang.code)
  )

  const installed = languages.installed.map(x => ({
    ...x,
    ...languages.available.find(l => l.code === x.lang)
  }))

  return (
    <React.Fragment>
      {languages && languages.available.length > 0 && !props.readOnly && !!downloadables.length && (
        <div className="languages-list">
          {/* TODO add a select when we have too many languages */}
          <h4>Add Languages</h4>
          {downloadables.map(lang => (
            <Language
              key={lang.code}
              language={lang}
              installed={false}
              loaded={false}
              allowActions={!props.readOnly}
              languageSource={props.languageSource}
              downloadProgress={languages.downloading.find(l => l.lang == lang.code)}
            />
          ))}
        </div>
      )}
      <div className="languages-list">
        <h4>Installed Languages</h4>
        {installed.length === 0 && <p>No languages yet</p>}
        {installed.map(lang => (
          <Language
            key={lang.code}
            language={lang}
            installed={true}
            loaded={lang.loaded}
            allowActions={!props.readOnly}
            languageSource={props.languageSource}
          />
        ))}
      </div>
    </React.Fragment>
  )
}

export default LanguageManagement

{'fraction_non_alphanumeric': 0.14017639331957216, 'fraction_numerical': 0.004503659223118784, 'mean_word_length': 2.5415282392026577, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 11, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3227801', 'n_tokens_mistral': 1544, 'n_tokens_neox': 1515, 'n_words': 341}