Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/i18n-keysets/component.collections-structure/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"action_stay": "Remain",
"button_choose-file": "Select a file",
"button_deploy": "Deploy",
"label_collection-already-exists-error": "The collection already exists",
"label_connection": "connection",
"label_copy": "Copy to",
"label_copy-denied-title": "Insufficient permissions to copy",
Expand All @@ -38,11 +39,14 @@
"label_report": "report",
"label_title": "Name",
"label_wizard": "chart",
"label_workbook-already-exists-error": "The workbook already exists",
"section_delete-collection": "Are you sure you want to delete the collection \"{{name}}\"?",
"section_delete-workbook": "Are you sure you want to delete the workbook \"{{name}}\"?",
"title_deploy": "Deploy to",
"title_import-exit": "Do you want to close the import window?",
"toast_collection-already-exists-error": "The collection already exists",
"toast_get-gallery-file-error": "Deployment error, please contact the support service",
"toast_get-json-error": "An error occurred while trying to get a JSON from the file",
"toast_outdated-workbook-info": "The workbook information is outdated. Please refresh the page."
"toast_outdated-workbook-info": "The workbook information is outdated. Please refresh the page.",
"toast_workbook-already-exists-error": "The workbook already exists"
}
6 changes: 5 additions & 1 deletion src/i18n-keysets/component.collections-structure/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"action_stay": "Остаться",
"button_choose-file": "Выбрать файл",
"button_deploy": "Развернуть",
"label_collection-already-exists-error": "Коллекция уже существует",
"label_connection": "подключения",
"label_copy": "Куда копировать",
"label_copy-denied-title": "Недостаточно прав для копирования",
Expand All @@ -38,11 +39,14 @@
"label_report": "отчёта",
"label_title": "Название",
"label_wizard": "чарта",
"label_workbook-already-exists-error": "Воркбук уже существует",
"section_delete-collection": "Вы действительно хотите удалить коллекцию \"{{name}}\"?",
"section_delete-workbook": "Вы действительно хотите удалить воркбук \"{{name}}\"?",
"title_deploy": "Куда развернуть",
"title_import-exit": "Закрыть окно импорта?",
"toast_collection-already-exists-error": "Коллекция уже существует",
"toast_get-gallery-file-error": "Ошибка при развёртывании, обратитесь в поддержку",
"toast_get-json-error": "Ошибка при попытке получить JSON из файла",
"toast_outdated-workbook-info": "Информация о воркбуке устарела. Пожалуйста, обновите страницу."
"toast_outdated-workbook-info": "Информация о воркбуке устарела. Пожалуйста, обновите страницу.",
"toast_workbook-already-exists-error": "Воркбук уже существует"
}
3 changes: 3 additions & 0 deletions src/shared/constants/error-codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ export enum ErrorCode {

ChartEditorNotAvailable = 'ERR.CHARTS.CHART_EDITOR_NOT_AVAILABLE',
InsufficientServicePlan = 'ERR.CHARTS.INSUFFICIENT_SERVICE_PLAN',
WorkbookAlreadyExists = 'WORKBOOK_ALREADY_EXISTS',
MetaManagerWorkbookAlreadyExists = 'META_MANAGER.WORKBOOK_ALREADY_EXISTS',
CollectionAlreadyExists = 'COLLECTION_ALREADY_EXISTS',
}

export const ErrorContentTypes = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,52 @@ const i18n = I18n.keyset('component.collections-structure');

const b = block('dl-collection-dialog');

export type CollectionDialogValues = {
title: string;
description: string;
};

type CollectionDialogErrors = Partial<Record<keyof CollectionDialogValues, string>>;

export type Props = {
title: string;
textButtonApply: string;
open: boolean;
isLoading: boolean;
titleValue?: string;
descriptionValue?: string;
titleAutoFocus?: boolean;
onApply: (args: {title: string; description: string}) => Promise<unknown>;
onChange: (values: CollectionDialogValues) => void;
onApply: (values: CollectionDialogValues, onClose: () => void) => Promise<unknown>;
onClose: () => void;
};
} & {values: CollectionDialogValues} & {errors?: CollectionDialogErrors};

export const CollectionDialog = React.memo<Props>(
({
values,
errors,
title,
textButtonApply,
open,
isLoading,
titleValue = '',
descriptionValue = '',
titleAutoFocus = false,
onApply,
onChange,
onClose,
}) => {
const [innerTitleValue, setInnerTitleValue] = React.useState(titleValue);
const [innerDescriptionValue, setInnerDescriptionValue] = React.useState(descriptionValue);
const handleChange = React.useCallback(
(params) => {
const {target} = params;

React.useEffect(() => {
if (open) {
setInnerTitleValue(titleValue);
setInnerDescriptionValue(descriptionValue);
}
}, [open, titleValue, descriptionValue]);
onChange({
...values,
[target.name]: target.value,
});
},
[onChange, values],
);

const handleApply = React.useCallback(() => {
onApply({title: innerTitleValue, description: innerDescriptionValue}).then(() => {
onClose();
});
}, [innerTitleValue, innerDescriptionValue, onApply, onClose]);
onApply(values, onClose);
}, [onApply, values, onClose]);

return (
<Dialog
Expand All @@ -63,16 +70,20 @@ export const CollectionDialog = React.memo<Props>(
<div className={b('field')}>
<div className={b('title')}>{i18n('label_title')}</div>
<TextInput
value={innerTitleValue}
onUpdate={setInnerTitleValue}
name="title"
value={values.title}
error={errors?.title}
onChange={handleChange}
autoFocus={titleAutoFocus}
/>
</div>
<div className={b('field')}>
<div className={b('title')}>{i18n('label_description')}</div>
<TextArea
value={innerDescriptionValue}
onUpdate={setInnerDescriptionValue}
name="description"
value={values.description}
error={errors?.description}
onChange={handleChange}
minRows={2}
/>
</div>
Expand All @@ -82,7 +93,7 @@ export const CollectionDialog = React.memo<Props>(
onClickButtonApply={handleApply}
textButtonApply={textButtonApply}
propsButtonApply={{
disabled: !innerTitleValue,
disabled: !values.title,
}}
textButtonCancel={i18n('action_cancel')}
loading={isLoading}
Expand Down
56 changes: 43 additions & 13 deletions src/ui/components/CollectionsStructure/CreateCollectionDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import React from 'react';

import {I18n} from 'i18n';
import {useDispatch, useSelector} from 'react-redux';
import {ErrorCode} from 'shared/constants';
import type {CreateCollectionResponse} from 'shared/schema';
import type {AppDispatch} from 'store';

import DialogManager from '../../components/DialogManager/DialogManager';
import {createCollection} from '../../store/actions/collectionsStructure';
import {selectCreateCollectionIsLoading} from '../../store/selectors/collectionsStructure';

import {CollectionDialog} from './CollectionDialog';
import {CollectionDialog, type CollectionDialogValues} from './CollectionDialog';
import {useCollectionEntityDialogState} from './hooks/useCollectionEntityDialogState';

const i18n = I18n.keyset('component.collections-structure');

Expand All @@ -30,33 +32,61 @@ type Props = {
export const CreateCollectionDialog: React.FC<Props> = (props) => {
const dispatch: AppDispatch = useDispatch();
const {open, onClose} = props;
const {
values: dialogValues,
errors: dialogErrors,
handleChange: handleDialogChange,
handleError: handleDialogError,
} = useCollectionEntityDialogState({
title: '',
description: '',
});

const handleApply = async ({title, description}: {title: string; description: string}) => {
const handleApply = async (
{title, description}: CollectionDialogValues,
dialogOnClose: () => void,
) => {
const {parentId, onApply} = props;

const result = await dispatch(
createCollection({
title,
description,
parentId,
}),
);
try {
const result = await dispatch(
createCollection(
{
title,
description,
parentId,
},
true,
),
);

if (onApply) {
onApply(result);
}
if (onApply) {
onApply(result);
}

dialogOnClose();

return result;
return result;
} catch (error) {
if (error.code === ErrorCode.CollectionAlreadyExists) {
handleDialogError({title: i18n('label_collection-already-exists-error')});
}

return Promise.resolve();
}
};

const isLoading = useSelector(selectCreateCollectionIsLoading);

return (
<CollectionDialog
values={dialogValues}
errors={dialogErrors}
title={i18n('action_create-collection')}
textButtonApply={i18n('action_create')}
open={open}
isLoading={isLoading}
onChange={handleDialogChange}
onApply={handleApply}
onClose={onClose}
titleAutoFocus
Expand Down
Loading
Loading