Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions src/entities/transformation/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ const SHOW_BUTTONS_CONTEXT_INITIAL_VALUE: ShowButtonsContextProps = {
isDisplayed: true,
};

export const TRANSFORMATION_RESPONSE_LOCATION_POSITION = {
CATEGORY: 1,
TRANSFORMATION_TYPE: 3,
};

export const ShowButtonsContext = createContext<ShowButtonsContextProps>(SHOW_BUTTONS_CONTEXT_INITIAL_VALUE);

export const TRANSFORMATIONS_FORM_DEFAULT_VALUE: TransformationsForm = {
Expand Down
3 changes: 2 additions & 1 deletion src/entities/transformation/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './prepareTransformationRequest';
export * from './prepareTransformationForm';
export * from './prepareTransformationFormError';
export * from './prepareTransformationRequest';
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { FormFieldError } from '@shared/config';

import { TransformationType } from '../../types';

import { TRANSFORMATION_RESPONSE_LOCATION_POSITION } from './../../constants';

/** Util for preparing received errors for use on a form */
export const prepareTransformationFormError = (errors: FormFieldError[]): FormFieldError[] => {
return errors.map((error) => {
const { location } = error;
if (location[TRANSFORMATION_RESPONSE_LOCATION_POSITION.CATEGORY] !== 'transformations') return error;

switch (
(location as string[])[TRANSFORMATION_RESPONSE_LOCATION_POSITION.TRANSFORMATION_TYPE] as TransformationType
) {
case TransformationType.FILTER_SQL:
//location : ['body', 'transformations', 3, 'sql', 'query']
/* From the backend, the error record comes in a simple form in accordance with the api.
Return it to the state it was stored in the form */
const insertPosition = TRANSFORMATION_RESPONSE_LOCATION_POSITION.TRANSFORMATION_TYPE + 1;
const newLocation = location.slice(0, insertPosition).concat(0).concat(location.slice(insertPosition));
return { ...error, location: newLocation } as FormFieldError;

default:
return error;
}
});
};
2 changes: 1 addition & 1 deletion src/shared/config/errors/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interface DefaultError {
type LocationTypeError = 'body' | 'query';

export interface FormFieldError extends DefaultError {
location: [Extract<LocationTypeError, 'body'>, string];
location: [Extract<LocationTypeError, 'body'>, string | number];
}

export interface MessageError {
Expand Down
9 changes: 6 additions & 3 deletions src/shared/ui/ManagedForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useLayoutEffect, useState } from 'react';
import { useLayoutEffect, useState } from 'react';
import { Form, notification, Spin } from 'antd';
import { PropsWithChildren } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { clsx } from 'clsx';
import { checkIsFormFieldsError, getErrorMessage } from '@shared/config';
import { checkIsFormFieldsError, FormFieldError, getErrorMessage } from '@shared/config';
import { useTranslation } from 'react-i18next';

import * as classes from './styles.module.less';
Expand All @@ -19,6 +19,7 @@ export const ManagedForm = <T extends object, R>({
keysInvalidateQueries = [],
isHiddenLoadingOnSuccess = false,
onError = () => undefined,
prepareFormErrors,
...props
}: PropsWithChildren<ManagedFormProps<T, R>>) => {
const { t, i18n } = useTranslation('error');
Expand Down Expand Up @@ -51,7 +52,9 @@ export const ManagedForm = <T extends object, R>({

if (checkIsFormFieldsError(error) && error.response) {
message = t('formErrorHasOccurred');
showErrorsInFields(form, error.response.data.error.details);
const errors: FormFieldError[] = error.response.data.error.details;
const preparedErrors = prepareFormErrors ? prepareFormErrors(errors) : errors;
showErrorsInFields(form, preparedErrors);
}

notification.error({
Expand Down
3 changes: 3 additions & 0 deletions src/shared/ui/ManagedForm/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { FormFieldError } from '@shared/config';
import { QueryClient } from '@tanstack/react-query';
import { FormProps } from 'antd';

Expand All @@ -20,4 +21,6 @@ export interface ManagedFormProps<T, R> extends Omit<FormProps<T>, 'form' | 'onF
keysInvalidateQueries?: Parameters<QueryClient['invalidateQueries']>[];
/** Flag that hides a spin if the request is successful */
isHiddenLoadingOnSuccess?: boolean;
/** Callback to prepare received errors */
prepareFormErrors?: (errors: FormFieldError[]) => FormFieldError[];
}
4 changes: 2 additions & 2 deletions src/shared/ui/ManagedForm/utils/showErrorsInFields/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ export const showErrorsInFields = (form: FormInstance, errors: FormFieldError[])
const fieldErrors = errors
.map((field) => {
// Keep only valid parts of the path
const validPath = field.location.reduce<string[]>((acc, key) => {
const validPath = field.location.reduce<Array<string | number>>((acc, key) => {
const currentPath = [...acc, key];
// Check if the path to the current key exists
if (typeof form.getFieldValue(currentPath) === 'object' || form.getFieldInstance(currentPath)) {
if (typeof form.getFieldValue(currentPath) === 'object' || form.isFieldTouched(currentPath)) {
acc.push(key);
}
return acc;
Expand Down
4 changes: 2 additions & 2 deletions src/widgets/transfer/CreateTransfer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React from 'react';
import { ManagedForm } from '@shared/ui';
import { useNavigate } from 'react-router-dom';
import { prepareTransferResourcesRequest, Transfer, TransferQueryKey, transferService } from '@entities/transfer';
import { MutateTransferForm } from '@features/transfer';
import { prepareTransformationRequest } from '@entities/transformation';
import { prepareTransformationFormError, prepareTransformationRequest } from '@entities/transformation';
import { useTranslation } from 'react-i18next';

import { CreateTransferForm, CreateTransferProps } from './types';
Expand Down Expand Up @@ -36,6 +35,7 @@ export const CreateTransfer = ({ group }: CreateTransferProps) => {
mutationFunction={handleCreateTransfer}
onSuccess={onSuccess}
successMessage={t('createTransferSuccess')}
prepareFormErrors={prepareTransformationFormError}
keysInvalidateQueries={[[{ queryKey: [TransferQueryKey.GET_TRANSFERS, group.id] }]]}
>
<MutateTransferForm group={group} onCancel={onCancel} />
Expand Down
7 changes: 6 additions & 1 deletion src/widgets/transfer/UpdateTransfer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import {
transferService,
} from '@entities/transfer';
import { MutateTransferForm } from '@features/transfer';
import { prepareTransformationForm, prepareTransformationRequest } from '@entities/transformation';
import {
prepareTransformationForm,
prepareTransformationFormError,
prepareTransformationRequest,
} from '@entities/transformation';
import { useTranslation } from 'react-i18next';

import { UpdateTransferForm, UpdateTransferProps } from './types';
Expand Down Expand Up @@ -47,6 +51,7 @@ export const UpdateTransfer = ({ transfer, group }: UpdateTransferProps) => {
mutationFunction={handleUpdateTransfer}
onSuccess={onSuccess}
successMessage={t('updateTransferSuccess')}
prepareFormErrors={prepareTransformationFormError}
keysInvalidateQueries={[
[{ queryKey: [TransferQueryKey.GET_TRANSFERS, group.id] }],
[{ queryKey: [TransferQueryKey.GET_TRANSFER, transfer.id] }],
Expand Down