Ott 92 lexics (#21)
parent
3e28a86d08
commit
f503c7ec79
@ -1,14 +1,16 @@ |
|||||||
import React, { ReactNode } from 'react' |
import React, { ReactNode } from 'react' |
||||||
|
|
||||||
import { AuthStore } from 'features/AuthStore' |
import { AuthStore } from 'features/AuthStore' |
||||||
|
import { LexicsStore } from 'features/LexicsStore' |
||||||
|
|
||||||
type Props = { |
type Props = { |
||||||
children: ReactNode, |
children: ReactNode, |
||||||
} |
} |
||||||
|
|
||||||
// аутентификация, лексики и другие глобальные сторы
|
|
||||||
export const GlobalStores = ({ children }: Props) => ( |
export const GlobalStores = ({ children }: Props) => ( |
||||||
<AuthStore> |
<AuthStore> |
||||||
{children} |
<LexicsStore> |
||||||
|
{children} |
||||||
|
</LexicsStore> |
||||||
</AuthStore> |
</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