ElectronicBabylonianLiterature/ebl-frontend

View on GitHub
src/transliteration/ui/GlossaryLine.tsx

Summary

Maintainability
A
1 hr
Test Coverage
A
100%
import React, { useState } from 'react'
import _ from 'lodash'
import { Link } from 'react-router-dom'
import DisplayToken from 'transliteration/ui/DisplayToken'
import { GlossaryToken } from 'transliteration/domain/glossary'
import { Label, statusAbbreviation } from 'transliteration/domain/labels'
import DictionaryWord from 'dictionary/domain/Word'
import lineNumberToString from 'transliteration/domain/lineNumberToString'
import {
  createLemmaMap,
  LemmaMap,
  LineLemmasContext,
} from './LineLemmasContext'

export default function GlossaryLine({
  tokens,
}: {
  tokens: readonly GlossaryToken[]
}): JSX.Element {
  return (
    <div>
      <GlossaryLemma word={tokens[0].dictionaryWord as DictionaryWord} />
      {', '}
      <GlossaryGuideword word={tokens[0].dictionaryWord as DictionaryWord} />
      {': '}
      {_(tokens)
        .groupBy((token) => token.value)
        .toPairs()
        .map(([value, tokensByValue], index) => (
          <React.Fragment key={value}>
            {index > 0 && ', '}
            <GlossaryWord tokens={tokensByValue} />
          </React.Fragment>
        ))
        .value()}
    </div>
  )
}

function GlossaryLemma({ word }: { word: DictionaryWord }): JSX.Element {
  return (
    <Link to={`/dictionary/${word._id}`}>
      <span className="Glossary__lemma">{word.lemma.join(' ')}</span>
      {word.homonym !== 'I' && (
        <span className="Glossary__homonym"> {word.homonym}</span>
      )}
    </Link>
  )
}

function GlossaryGuideword({ word }: { word: DictionaryWord }): JSX.Element {
  return <>“{word.guideWord}”</>
}

function GlossaryWord({
  tokens,
}: {
  tokens: readonly GlossaryToken[]
}): JSX.Element {
  const word = _.head(tokens)?.word
  const [lemmaMap, lemmaSetter] = useState<LemmaMap>(
    createLemmaMap(tokens.map((token) => token.uniqueLemma))
  )

  return (
    <LineLemmasContext.Provider
      value={{
        lemmaMap: lemmaMap,
        lemmaSetter: lemmaSetter,
      }}
    >
      <span className="Transliteration">
        {word && <DisplayToken token={word} />}
      </span>
      {_(tokens)
        .map('label')
        .uniq()
        .map((label, index) => (
          <React.Fragment key={index}>
            {index > 0 ? ', ' : ' ('}
            {_.compact([label.object, label.surface, label.column])
              .map((singleLabel, index) => (
                <GlossaryLabel key={index} label={singleLabel} />
              ))
              .concat(
                <React.Fragment key="line number">
                  {label.line && lineNumberToString(label.line)}
                </React.Fragment>
              )}
          </React.Fragment>
        ))
        .value()}
      )
    </LineLemmasContext.Provider>
  )
}

function GlossaryLabel({
  label: { abbreviation, status },
}: {
  label: Label
}): JSX.Element {
  return (
    <>
      {abbreviation}
      {status && <sup>{status.map(statusAbbreviation)}</sup>}{' '}
    </>
  )
}