src/renderer/components/dictionaries-modal/index.tsx (246 lines of code) (raw):
import { SyntheticEvent, useEffect, useState } from 'react';
import {
AddDictionaryType,
DictionariesVersionsType,
DICTIONARY_LABELS,
DictionaryCommonType,
DictionaryType,
ErrorType,
SelectedDictionariesType
} from '@common';
import { ErrorContent } from '@components';
import { AVAILABLE_DICTIONARY_TYPES, AVAILABLE_DICTIONARY_VERSIONS, DICTIONARIES_MODAL_STATES, NOT_SELECTED_DICTIONARY } from '@constants';
import { DictionariesModalState, SelectChangeEvent } from '@types';
import { DictionaryTab, DictionaryTabs, Modal, OutlinedButton, PrimaryButton, Select, Spinner, TextButton } from '@ui-kit';
import { getFormattedDictionaryVersions } from '@utils';
import {
AddTitle,
AddWrapper,
ChooseWrapper,
CorruptWrapper,
DictionaryLabel,
ErrorMessage,
ErrorTitle,
InstallMessage,
InstallWrapper,
ReplaceTitle,
ReplaceWrapper,
Toolbar,
Wrapper
} from './parts';
type CorruptContentProps = {
dictionary: DictionaryCommonType;
handleCancel: () => void;
handleReplace: (dictionary: AddDictionaryType) => () => Promise<void>;
};
export const CorruptContent = ({ dictionary, handleCancel, handleReplace }: CorruptContentProps) => {
const { type, version } = dictionary;
return (
<CorruptWrapper>
<ErrorTitle>Dictionary Is Corrupted</ErrorTitle>
<ErrorMessage>
Some of<DictionaryLabel>{` ${DICTIONARY_LABELS[type]} ${version} `}</DictionaryLabel>files were removed or corrupted. Please
reinstall this dictionary
</ErrorMessage>
<Toolbar>
<TextButton title="Cancel" onClick={handleCancel} />
<OutlinedButton title="Replace" onClick={handleReplace({ type, version, replace: true })} />
</Toolbar>
</CorruptWrapper>
);
};
export const InstallContent = () => (
<InstallWrapper>
<InstallMessage>Installing...</InstallMessage>
<Spinner size={80} />
</InstallWrapper>
);
type ReplaceContentProps = {
type: DictionaryType;
version: string;
handleCancel: () => void;
handleReplace: () => Promise<void>;
};
const ReplaceContent = ({ type, version, handleCancel, handleReplace }: ReplaceContentProps) => (
<ReplaceWrapper>
<ReplaceTitle>Dictionary Is Already Installed</ReplaceTitle>
<ErrorMessage>
<DictionaryLabel>{`${DICTIONARY_LABELS[type]} ${version}`}</DictionaryLabel>
{' is already installed.\nDo you want replace it?'}
</ErrorMessage>
<Toolbar>
<TextButton title="Cancel" onClick={handleCancel} />
<OutlinedButton title="Replace" onClick={handleReplace} />
</Toolbar>
</ReplaceWrapper>
);
type AddContentProps = {
type: DictionaryType;
version: string;
error?: ErrorType;
handleCancel: () => void;
handleBrowse: () => Promise<void>;
handleChangeVersion: (event: SelectChangeEvent<unknown>) => void;
handleChangeType: (_: SyntheticEvent, type: DictionaryType) => void;
};
const AddContent = ({ type, version, handleChangeType, handleChangeVersion, handleCancel, handleBrowse, error }: AddContentProps) => (
<AddWrapper>
<AddTitle>Type of dictionary</AddTitle>
<DictionaryTabs value={type} variant="scrollable" onChange={handleChangeType}>
{AVAILABLE_DICTIONARY_TYPES.map((dictionaryType) => (
<DictionaryTab key={dictionaryType} label={DICTIONARY_LABELS[dictionaryType]} value={dictionaryType} disableRipple />
))}
</DictionaryTabs>
<Select
error={error?.message}
handleChange={handleChangeVersion}
label="Version"
options={AVAILABLE_DICTIONARY_VERSIONS[type]}
value={version}
/>
<Toolbar>
<TextButton title="Cancel" onClick={handleCancel} />
<PrimaryButton title="Browse Dictionary" onClick={handleBrowse} />
</Toolbar>
</AddWrapper>
);
type ChooseContentProps = {
dictionaryVersions: DictionariesVersionsType;
preselectedDictionaries: SelectedDictionariesType;
handleChangeVersion: (dictionary: DictionaryType) => (event: SelectChangeEvent<unknown>) => void;
handleAdd: () => void;
handleConfirm: () => void;
};
const ChooseContent = ({
dictionaryVersions,
preselectedDictionaries,
handleChangeVersion,
handleAdd,
handleConfirm
}: ChooseContentProps) => {
const renderAvailableDictionaries = (availableDictionaries: DictionaryType[]) =>
availableDictionaries.map(
(type) =>
dictionaryVersions[type] && (
<Select
key={type}
handleChange={handleChangeVersion(type)}
label={DICTIONARY_LABELS[type]}
options={getFormattedDictionaryVersions(dictionaryVersions[type]!)}
value={preselectedDictionaries[type] || NOT_SELECTED_DICTIONARY}
/>
)
);
return (
<ChooseWrapper>
{renderAvailableDictionaries(AVAILABLE_DICTIONARY_TYPES)}
<Toolbar>
<TextButton title="Add Dictionary" onClick={handleAdd} />
<PrimaryButton title="Confirm" onClick={handleConfirm} />
</Toolbar>
</ChooseWrapper>
);
};
type DictionariesModalProps = {
open: boolean;
modalState: DictionariesModalState;
dictionaryVersions: DictionariesVersionsType;
preselectedDictionaries: SelectedDictionariesType;
corruptedDictionary?: DictionaryCommonType;
error?: ErrorType;
handleChangePreselectedVersion: (dictionary: DictionaryType) => (event: SelectChangeEvent<unknown>) => void;
closeModal: () => void;
handleCancel: () => void;
handleOpenAdd: () => void;
handleConfirm: () => void;
handleInstall: (dictionary: AddDictionaryType) => () => Promise<void>;
closeError: () => void;
clearError: () => void;
};
export const DictionariesModal = ({
open,
modalState,
dictionaryVersions,
preselectedDictionaries,
corruptedDictionary,
error,
handleChangePreselectedVersion,
closeModal,
handleInstall,
handleCancel,
handleOpenAdd,
handleConfirm,
closeError,
clearError
}: DictionariesModalProps) => {
const [type, setType] = useState<DictionaryType>(AVAILABLE_DICTIONARY_TYPES[0]);
const [versions, setVersions] = useState<SelectedDictionariesType>({});
const setDefault = () => {
setType(AVAILABLE_DICTIONARY_TYPES[0]);
setVersions({});
};
const handleChangeVersion = (type: DictionaryType) => (event: SelectChangeEvent<unknown>) => {
clearError();
setVersions((prevState) => ({ ...prevState, [type]: event.target.value as string }));
};
const handleChangeType = (_: SyntheticEvent, type: DictionaryType) => {
clearError();
setType(type);
};
const handleAdd = () => {
setDefault();
handleOpenAdd();
};
const titleByState = {
[DICTIONARIES_MODAL_STATES.add]: 'Add Dictionary',
[DICTIONARIES_MODAL_STATES.choose]: 'Dictionaries'
};
const closeByState = {
[DICTIONARIES_MODAL_STATES.add]: handleCancel,
[DICTIONARIES_MODAL_STATES.choose]: closeModal
};
useEffect(() => {
if (open) {
setDefault();
}
}, [open]);
return (
<Modal handleClose={closeByState[modalState]} open={open} title={titleByState[modalState]}>
<Wrapper>
{modalState === DICTIONARIES_MODAL_STATES.replace && (
<ReplaceContent
handleCancel={handleCancel}
handleReplace={handleInstall({ type, version: versions[type] || '', replace: true })}
type={type}
version={versions[type] || ''}
/>
)}
{modalState === DICTIONARIES_MODAL_STATES.add && (
<AddContent
error={error}
handleBrowse={handleInstall({ type, version: versions[type] || '' })}
handleCancel={handleCancel}
handleChangeType={handleChangeType}
handleChangeVersion={handleChangeVersion(type)}
type={type}
version={versions[type] || ''}
/>
)}
{modalState === DICTIONARIES_MODAL_STATES.choose && (
<ChooseContent
dictionaryVersions={dictionaryVersions}
handleAdd={handleAdd}
handleChangeVersion={handleChangePreselectedVersion}
handleConfirm={handleConfirm}
preselectedDictionaries={preselectedDictionaries}
/>
)}
{modalState === DICTIONARIES_MODAL_STATES.install && <InstallContent />}
{modalState === DICTIONARIES_MODAL_STATES.corrupt && (
<CorruptContent dictionary={corruptedDictionary!} handleCancel={handleCancel} handleReplace={handleInstall} />
)}
{modalState === DICTIONARIES_MODAL_STATES.error && error && <ErrorContent error={error} handleClose={closeError} />}
</Wrapper>
</Modal>
);
};