Ott 92 lexics (#21)
parent
3e28a86d08
commit
f503c7ec79
@ -1,14 +1,16 @@ |
||||
import React, { ReactNode } from 'react' |
||||
|
||||
import { AuthStore } from 'features/AuthStore' |
||||
import { LexicsStore } from 'features/LexicsStore' |
||||
|
||||
type Props = { |
||||
children: ReactNode, |
||||
} |
||||
|
||||
// аутентификация, лексики и другие глобальные сторы
|
||||
export const GlobalStores = ({ children }: Props) => ( |
||||
<AuthStore> |
||||
<LexicsStore> |
||||
{children} |
||||
</LexicsStore> |
||||
</AuthStore> |
||||
) |
||||
|
||||
@ -0,0 +1,35 @@ |
||||
import { mapTranslationsToLocalKeys } from '..' |
||||
|
||||
const createTranslation = (id: string) => ({ |
||||
id, |
||||
lang: '', |
||||
lexis_lang_id: '', |
||||
text: '', |
||||
}) |
||||
|
||||
it('returns empty object for empty args', () => { |
||||
const translations = {} |
||||
const config = {} |
||||
const expected = {} |
||||
|
||||
const result = mapTranslationsToLocalKeys(translations, config) |
||||
expect(result).toEqual(expected) |
||||
}) |
||||
|
||||
it('empty translations when config is empty', () => { |
||||
const translations = { 1: createTranslation('1') } |
||||
const lexicsConfig = {} |
||||
const expected = {} |
||||
|
||||
const result = mapTranslationsToLocalKeys(translations, lexicsConfig) |
||||
expect(result).toEqual(expected) |
||||
}) |
||||
|
||||
it('translations with lexic key specified in config', () => { |
||||
const translations = { 1: createTranslation('1'), 2: createTranslation('2') } |
||||
const lexicsConfig = { 2: 2, formInput: 1 } |
||||
const expected = { 2: translations[2], formInput: translations[1] } |
||||
|
||||
const result = mapTranslationsToLocalKeys(translations, lexicsConfig) |
||||
expect(result).toEqual(expected) |
||||
}) |
||||
@ -0,0 +1,60 @@ |
||||
import isArray from 'lodash/isArray' |
||||
import entries from 'lodash/entries' |
||||
import reduce from 'lodash/reduce' |
||||
import uniq from 'lodash/uniq' |
||||
import map from 'lodash/map' |
||||
|
||||
import type { Translations } from 'requests' |
||||
|
||||
import type { LexicsId, LexicsConfig } from '../types' |
||||
|
||||
const LANG_KEY = 'lang' |
||||
const defaultLang = 'en' |
||||
|
||||
export const writeLang = (lang: string) => { |
||||
localStorage.setItem(LANG_KEY, lang) |
||||
} |
||||
|
||||
export const readLang = () => { |
||||
const lang = localStorage.getItem(LANG_KEY) |
||||
if (lang) return lang |
||||
|
||||
writeLang(defaultLang) |
||||
return defaultLang |
||||
} |
||||
|
||||
export const getSuffix = (lang: string) => ( |
||||
lang === 'rus' ? 'rus' : 'eng' |
||||
) |
||||
|
||||
export const getLexicIds = (ids: Array<LexicsId> | LexicsConfig) => ( |
||||
uniq(map(ids, (id) => Number(id))) |
||||
) |
||||
|
||||
export const getObjectConfig = (ids: Array<LexicsId> | LexicsConfig) => { |
||||
if (isArray(ids)) { |
||||
return reduce( |
||||
ids, |
||||
(acc, id) => ({ ...acc, [id]: id }), |
||||
{}, |
||||
) |
||||
} |
||||
return ids |
||||
} |
||||
|
||||
export const mapTranslationsToLocalKeys = ( |
||||
translations: Translations, |
||||
lexicsConfig: LexicsConfig, |
||||
) => { |
||||
const pairs = entries(lexicsConfig) |
||||
return reduce( |
||||
pairs, |
||||
(acc, [key, id]) => { |
||||
if (translations[id]) { |
||||
acc[key] = translations[id] |
||||
} |
||||
return acc |
||||
}, |
||||
{} as Translations, |
||||
) |
||||
} |
||||
@ -0,0 +1,50 @@ |
||||
import { useEffect, useCallback } from 'react' |
||||
|
||||
import isEmpty from 'lodash/isEmpty' |
||||
|
||||
import { getLexics } from 'requests' |
||||
|
||||
import { |
||||
getLexicIds, |
||||
mapTranslationsToLocalKeys, |
||||
} from 'features/LexicsStore/helpers' |
||||
|
||||
import { useLang } from './useLang' |
||||
import { useLexicsConfig } from './useLexicsConfig' |
||||
import { useTranslations } from './useTranslations' |
||||
|
||||
export const useLexics = () => { |
||||
const { changeLang, lang } = useLang() |
||||
const { addLexicsConfig, lexicsConfig } = useLexicsConfig() |
||||
const { addTranslations, translate } = useTranslations() |
||||
|
||||
const fetchLexics = useCallback( |
||||
async () => { |
||||
const lexicIds = getLexicIds(lexicsConfig) |
||||
if (isEmpty(lexicIds)) return |
||||
|
||||
const newTranslations = await getLexics(lang, lexicIds) |
||||
addTranslations(mapTranslationsToLocalKeys(newTranslations, lexicsConfig)) |
||||
}, |
||||
[ |
||||
lang, |
||||
lexicsConfig, |
||||
addTranslations, |
||||
], |
||||
) |
||||
|
||||
useEffect(() => { |
||||
fetchLexics() |
||||
}, [ |
||||
lang, |
||||
lexicsConfig, |
||||
fetchLexics, |
||||
]) |
||||
|
||||
return { |
||||
addLexicsConfig, |
||||
changeLang, |
||||
lang, |
||||
translate, |
||||
} |
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
import { useState, useCallback } from 'react' |
||||
|
||||
import { readLang, writeLang } from 'features/LexicsStore/helpers' |
||||
|
||||
export const useLang = () => { |
||||
const [lang, setLang] = useState(readLang) |
||||
|
||||
const changeLang = useCallback( |
||||
(newLang: string) => { |
||||
if (newLang === lang) return |
||||
writeLang(newLang) |
||||
setLang(newLang) |
||||
}, |
||||
[lang], |
||||
) |
||||
|
||||
return { changeLang, lang } |
||||
} |
||||
@ -0,0 +1,19 @@ |
||||
import { useState, useCallback } from 'react' |
||||
|
||||
import { getObjectConfig } from 'features/LexicsStore/helpers' |
||||
|
||||
import type { LexicsConfig, LexicsId } from '../types' |
||||
|
||||
export const useLexicsConfig = () => { |
||||
const [lexicsConfig, setLexicsConfig] = useState<LexicsConfig>({}) |
||||
|
||||
const addLexicsConfig = useCallback( |
||||
(ids: Array<LexicsId> | LexicsConfig) => { |
||||
const config = getObjectConfig(ids) |
||||
setLexicsConfig((state) => ({ ...state, ...config })) |
||||
}, |
||||
[], |
||||
) |
||||
|
||||
return { addLexicsConfig, lexicsConfig } |
||||
} |
||||
@ -0,0 +1,26 @@ |
||||
import { useState, useCallback } from 'react' |
||||
|
||||
import type { Translations } from 'requests' |
||||
|
||||
import type { LexicsId } from '../types' |
||||
|
||||
export const useTranslations = () => { |
||||
const [translations, setTranslations] = useState<Translations>({}) |
||||
|
||||
const translate = useCallback( |
||||
(lexicId: LexicsId) => { |
||||
const translation = translations[lexicId] |
||||
return translation?.text || '' |
||||
}, |
||||
[translations], |
||||
) |
||||
|
||||
const addTranslations = useCallback( |
||||
(newTranslations: Translations) => { |
||||
setTranslations((state) => ({ ...state, ...newTranslations })) |
||||
}, |
||||
[], |
||||
) |
||||
|
||||
return { addTranslations, translate } |
||||
} |
||||
@ -0,0 +1,19 @@ |
||||
import type { ReactNode } from 'react' |
||||
import React, { |
||||
createContext, |
||||
useContext, |
||||
} from 'react' |
||||
|
||||
import { useLexics } from './hooks' |
||||
|
||||
type LexicsStore = ReturnType<typeof useLexics> |
||||
type Props = { children: ReactNode } |
||||
|
||||
const LexicsContext = createContext({} as LexicsStore) |
||||
|
||||
export const LexicsStore = ({ children }: Props) => { |
||||
const lexics = useLexics() |
||||
return <LexicsContext.Provider value={lexics}>{children}</LexicsContext.Provider> |
||||
} |
||||
|
||||
export const useLexicsStore = () => useContext(LexicsContext) |
||||
@ -0,0 +1,3 @@ |
||||
export type LexicsId = string |
||||
|
||||
export type LexicsConfig = {[lexicsId: string]: number} |
||||
@ -0,0 +1,16 @@ |
||||
import React from 'react' |
||||
import styled from 'styled-components/macro' |
||||
|
||||
import { useLexicsStore } from 'features/LexicsStore' |
||||
|
||||
const Text = styled.span`` |
||||
|
||||
type Props = { |
||||
className?: string, |
||||
t: string | number, |
||||
} |
||||
|
||||
export const T9n = ({ className, t }: Props) => { |
||||
const { translate } = useLexicsStore() |
||||
return <Text className={className}>{translate(String(t))}</Text> |
||||
} |
||||
@ -0,0 +1,30 @@ |
||||
import { DATA_URL, PROCEDURES } from 'config' |
||||
import { callApi, getResponseData } from 'helpers' |
||||
|
||||
const proc = PROCEDURES.param_lexical |
||||
|
||||
export type Translation = { |
||||
id: string, |
||||
lang: string, |
||||
lexis_lang_id: string, |
||||
text: string, |
||||
} |
||||
|
||||
export type Translations = {[id: string]: Translation} |
||||
|
||||
export const getLexics = (lang: string, lexicIds: Array<number>): Promise<Translations> => { |
||||
const config = { |
||||
body: { |
||||
params: { |
||||
_p_lang: lang, |
||||
_p_param_arr: lexicIds, |
||||
}, |
||||
proc, |
||||
}, |
||||
} |
||||
|
||||
return callApi({ |
||||
config, |
||||
url: DATA_URL, |
||||
}).then(getResponseData(proc)) |
||||
} |
||||
Loading…
Reference in new issue