mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Merge pull request #749 from Unleash/fix/context-form-validation
fix: handle context name errors before submitting the form
This commit is contained in:
		
						commit
						b485a6c900
					
				@ -1,9 +1,9 @@
 | 
			
		||||
import Input from '../../common/Input/Input';
 | 
			
		||||
import Input from 'component/common/Input/Input';
 | 
			
		||||
import { TextField, Button, Switch, Chip, Typography } from '@material-ui/core';
 | 
			
		||||
import { useStyles } from './ContextForm.styles';
 | 
			
		||||
import React, { useState } from 'react';
 | 
			
		||||
import { Add } from '@material-ui/icons';
 | 
			
		||||
import { trim } from '../../common/util';
 | 
			
		||||
import { trim } from 'component/common/util';
 | 
			
		||||
 | 
			
		||||
interface IContextForm {
 | 
			
		||||
    contextName: string;
 | 
			
		||||
@ -15,20 +15,20 @@ interface IContextForm {
 | 
			
		||||
    setStickiness: React.Dispatch<React.SetStateAction<boolean>>;
 | 
			
		||||
    setLegalValues: React.Dispatch<React.SetStateAction<string[]>>;
 | 
			
		||||
    handleSubmit: (e: any) => void;
 | 
			
		||||
    handleCancel: () => void;
 | 
			
		||||
    onCancel: () => void;
 | 
			
		||||
    errors: { [key: string]: string };
 | 
			
		||||
    mode: string;
 | 
			
		||||
    clearErrors: () => void;
 | 
			
		||||
    validateNameUniqueness: () => void;
 | 
			
		||||
    validateContext?: () => void;
 | 
			
		||||
    setErrors: React.Dispatch<React.SetStateAction<Object>>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ENTER = 'Enter';
 | 
			
		||||
 | 
			
		||||
const ContextForm: React.FC<IContextForm> = ({
 | 
			
		||||
export const ContextForm: React.FC<IContextForm> = ({
 | 
			
		||||
    children,
 | 
			
		||||
    handleSubmit,
 | 
			
		||||
    handleCancel,
 | 
			
		||||
    onCancel,
 | 
			
		||||
    contextName,
 | 
			
		||||
    contextDesc,
 | 
			
		||||
    legalValues,
 | 
			
		||||
@ -39,7 +39,7 @@ const ContextForm: React.FC<IContextForm> = ({
 | 
			
		||||
    setStickiness,
 | 
			
		||||
    errors,
 | 
			
		||||
    mode,
 | 
			
		||||
    validateNameUniqueness,
 | 
			
		||||
    validateContext,
 | 
			
		||||
    setErrors,
 | 
			
		||||
    clearErrors,
 | 
			
		||||
}) => {
 | 
			
		||||
@ -108,7 +108,7 @@ const ContextForm: React.FC<IContextForm> = ({
 | 
			
		||||
                    error={Boolean(errors.name)}
 | 
			
		||||
                    errorText={errors.name}
 | 
			
		||||
                    onFocus={() => clearErrors()}
 | 
			
		||||
                    onBlur={validateNameUniqueness}
 | 
			
		||||
                    onBlur={validateContext}
 | 
			
		||||
                    autoFocus
 | 
			
		||||
                />
 | 
			
		||||
                <p className={styles.inputDescription}>
 | 
			
		||||
@ -187,12 +187,10 @@ const ContextForm: React.FC<IContextForm> = ({
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className={styles.buttonContainer}>
 | 
			
		||||
                {children}
 | 
			
		||||
                <Button onClick={handleCancel} className={styles.cancelButton}>
 | 
			
		||||
                <Button onClick={onCancel} className={styles.cancelButton}>
 | 
			
		||||
                    Cancel
 | 
			
		||||
                </Button>
 | 
			
		||||
            </div>
 | 
			
		||||
        </form>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default ContextForm;
 | 
			
		||||
 | 
			
		||||
@ -1,16 +1,16 @@
 | 
			
		||||
import { useHistory } from 'react-router-dom';
 | 
			
		||||
import useUiConfig from '../../../hooks/api/getters/useUiConfig/useUiConfig';
 | 
			
		||||
import useToast from '../../../hooks/useToast';
 | 
			
		||||
import FormTemplate from '../../common/FormTemplate/FormTemplate';
 | 
			
		||||
import useContextForm from '../hooks/useContextForm';
 | 
			
		||||
import ContextForm from '../ContextForm/ContextForm';
 | 
			
		||||
import PermissionButton from '../../common/PermissionButton/PermissionButton';
 | 
			
		||||
import { CREATE_CONTEXT_FIELD } from '../../providers/AccessProvider/permissions';
 | 
			
		||||
import useContextsApi from '../../../hooks/api/actions/useContextsApi/useContextsApi';
 | 
			
		||||
import useUnleashContext from '../../../hooks/api/getters/useUnleashContext/useUnleashContext';
 | 
			
		||||
import { formatUnknownError } from '../../../utils/format-unknown-error';
 | 
			
		||||
import { useContextForm } from '../hooks/useContextForm';
 | 
			
		||||
import { ContextForm } from '../ContextForm/ContextForm';
 | 
			
		||||
import { CREATE_CONTEXT_FIELD } from 'component/providers/AccessProvider/permissions';
 | 
			
		||||
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
 | 
			
		||||
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
 | 
			
		||||
import useContextsApi from 'hooks/api/actions/useContextsApi/useContextsApi';
 | 
			
		||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
 | 
			
		||||
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
 | 
			
		||||
import useToast from 'hooks/useToast';
 | 
			
		||||
import { formatUnknownError } from 'utils/format-unknown-error';
 | 
			
		||||
 | 
			
		||||
const CreateContext = () => {
 | 
			
		||||
export const CreateContext = () => {
 | 
			
		||||
    const { setToastData, setToastApiError } = useToast();
 | 
			
		||||
    const { uiConfig } = useUiConfig();
 | 
			
		||||
    const history = useHistory();
 | 
			
		||||
@ -24,8 +24,7 @@ const CreateContext = () => {
 | 
			
		||||
        setLegalValues,
 | 
			
		||||
        setStickiness,
 | 
			
		||||
        getContextPayload,
 | 
			
		||||
        validateNameUniqueness,
 | 
			
		||||
        validateName,
 | 
			
		||||
        validateContext,
 | 
			
		||||
        clearErrors,
 | 
			
		||||
        setErrors,
 | 
			
		||||
        errors,
 | 
			
		||||
@ -35,7 +34,8 @@ const CreateContext = () => {
 | 
			
		||||
 | 
			
		||||
    const handleSubmit = async (e: Event) => {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
        const validName = validateName();
 | 
			
		||||
        const validName = await validateContext();
 | 
			
		||||
 | 
			
		||||
        if (validName) {
 | 
			
		||||
            const payload = getContextPayload();
 | 
			
		||||
            try {
 | 
			
		||||
@ -62,7 +62,7 @@ const CreateContext = () => {
 | 
			
		||||
--data-raw '${JSON.stringify(getContextPayload(), undefined, 2)}'`;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const handleCancel = () => {
 | 
			
		||||
    const onCancel = () => {
 | 
			
		||||
        history.goBack();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -78,7 +78,7 @@ const CreateContext = () => {
 | 
			
		||||
            <ContextForm
 | 
			
		||||
                errors={errors}
 | 
			
		||||
                handleSubmit={handleSubmit}
 | 
			
		||||
                handleCancel={handleCancel}
 | 
			
		||||
                onCancel={onCancel}
 | 
			
		||||
                contextName={contextName}
 | 
			
		||||
                setContextName={setContextName}
 | 
			
		||||
                contextDesc={contextDesc}
 | 
			
		||||
@ -88,7 +88,7 @@ const CreateContext = () => {
 | 
			
		||||
                stickiness={stickiness}
 | 
			
		||||
                setStickiness={setStickiness}
 | 
			
		||||
                mode="Create"
 | 
			
		||||
                validateNameUniqueness={validateNameUniqueness}
 | 
			
		||||
                validateContext={validateContext}
 | 
			
		||||
                setErrors={setErrors}
 | 
			
		||||
                clearErrors={clearErrors}
 | 
			
		||||
            >
 | 
			
		||||
@ -102,5 +102,3 @@ const CreateContext = () => {
 | 
			
		||||
        </FormTemplate>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default CreateContext;
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
import { useEffect } from 'react';
 | 
			
		||||
import { useHistory, useParams } from 'react-router-dom';
 | 
			
		||||
import { formatUnknownError } from 'utils/format-unknown-error';
 | 
			
		||||
import useContextsApi from '../../../hooks/api/actions/useContextsApi/useContextsApi';
 | 
			
		||||
import useContext from '../../../hooks/api/getters/useContext/useContext';
 | 
			
		||||
import useUiConfig from '../../../hooks/api/getters/useUiConfig/useUiConfig';
 | 
			
		||||
@ -8,11 +9,10 @@ import FormTemplate from '../../common/FormTemplate/FormTemplate';
 | 
			
		||||
import PermissionButton from '../../common/PermissionButton/PermissionButton';
 | 
			
		||||
import { scrollToTop } from '../../common/util';
 | 
			
		||||
import { UPDATE_CONTEXT_FIELD } from '../../providers/AccessProvider/permissions';
 | 
			
		||||
import ContextForm from '../ContextForm/ContextForm';
 | 
			
		||||
import useContextForm from '../hooks/useContextForm';
 | 
			
		||||
import { formatUnknownError } from '../../../utils/format-unknown-error';
 | 
			
		||||
import { ContextForm } from '../ContextForm/ContextForm';
 | 
			
		||||
import { useContextForm } from '../hooks/useContextForm';
 | 
			
		||||
 | 
			
		||||
const EditContext = () => {
 | 
			
		||||
export const EditContext = () => {
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        scrollToTop();
 | 
			
		||||
    }, []);
 | 
			
		||||
@ -33,8 +33,6 @@ const EditContext = () => {
 | 
			
		||||
        setLegalValues,
 | 
			
		||||
        setStickiness,
 | 
			
		||||
        getContextPayload,
 | 
			
		||||
        validateNameUniqueness,
 | 
			
		||||
        validateName,
 | 
			
		||||
        clearErrors,
 | 
			
		||||
        setErrors,
 | 
			
		||||
        errors,
 | 
			
		||||
@ -57,24 +55,21 @@ const EditContext = () => {
 | 
			
		||||
    const handleSubmit = async (e: Event) => {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
        const payload = getContextPayload();
 | 
			
		||||
        const validName = validateName();
 | 
			
		||||
 | 
			
		||||
        if (validName) {
 | 
			
		||||
            try {
 | 
			
		||||
                await updateContext(payload);
 | 
			
		||||
                refetch();
 | 
			
		||||
                history.push('/context');
 | 
			
		||||
                setToastData({
 | 
			
		||||
                    title: 'Context information updated',
 | 
			
		||||
                    type: 'success',
 | 
			
		||||
                });
 | 
			
		||||
            } catch (error: unknown) {
 | 
			
		||||
                setToastApiError(formatUnknownError(error));
 | 
			
		||||
            }
 | 
			
		||||
        try {
 | 
			
		||||
            await updateContext(payload);
 | 
			
		||||
            refetch();
 | 
			
		||||
            history.push('/context');
 | 
			
		||||
            setToastData({
 | 
			
		||||
                title: 'Context information updated',
 | 
			
		||||
                type: 'success',
 | 
			
		||||
            });
 | 
			
		||||
        } catch (e: unknown) {
 | 
			
		||||
            setToastApiError(formatUnknownError(e));
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const handleCancel = () => {
 | 
			
		||||
    const onCancel = () => {
 | 
			
		||||
        history.goBack();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -90,7 +85,7 @@ const EditContext = () => {
 | 
			
		||||
            <ContextForm
 | 
			
		||||
                errors={errors}
 | 
			
		||||
                handleSubmit={handleSubmit}
 | 
			
		||||
                handleCancel={handleCancel}
 | 
			
		||||
                onCancel={onCancel}
 | 
			
		||||
                contextName={contextName}
 | 
			
		||||
                setContextName={setContextName}
 | 
			
		||||
                contextDesc={contextDesc}
 | 
			
		||||
@ -100,7 +95,6 @@ const EditContext = () => {
 | 
			
		||||
                stickiness={stickiness}
 | 
			
		||||
                setStickiness={setStickiness}
 | 
			
		||||
                mode="Edit"
 | 
			
		||||
                validateNameUniqueness={validateNameUniqueness}
 | 
			
		||||
                setErrors={setErrors}
 | 
			
		||||
                clearErrors={clearErrors}
 | 
			
		||||
            >
 | 
			
		||||
@ -114,5 +108,3 @@ const EditContext = () => {
 | 
			
		||||
        </FormTemplate>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default EditContext;
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import { useEffect, useState } from 'react';
 | 
			
		||||
import useContextsApi from '../../../hooks/api/actions/useContextsApi/useContextsApi';
 | 
			
		||||
 | 
			
		||||
const useContextForm = (
 | 
			
		||||
export const useContextForm = (
 | 
			
		||||
    initialcontextName = '',
 | 
			
		||||
    initialcontextDesc = '',
 | 
			
		||||
    initialLegalValues = [] as string[],
 | 
			
		||||
@ -42,25 +42,28 @@ const useContextForm = (
 | 
			
		||||
 | 
			
		||||
    const NAME_EXISTS_ERROR = 'A context field with that name already exist';
 | 
			
		||||
 | 
			
		||||
    const validateNameUniqueness = async () => {
 | 
			
		||||
    const validateContext = async () => {
 | 
			
		||||
        if (contextName.length === 0) {
 | 
			
		||||
            setErrors(prev => ({ ...prev, name: 'Name can not be empty.' }));
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            await validateContextName(contextName);
 | 
			
		||||
            return true;
 | 
			
		||||
        } catch (e: any) {
 | 
			
		||||
            if (e.toString().includes(NAME_EXISTS_ERROR)) {
 | 
			
		||||
                setErrors(prev => ({
 | 
			
		||||
                    ...prev,
 | 
			
		||||
                    name: 'A context field with that name already exist',
 | 
			
		||||
                }));
 | 
			
		||||
            } else {
 | 
			
		||||
                setErrors(prev => ({
 | 
			
		||||
                    ...prev,
 | 
			
		||||
                    name: e.toString(),
 | 
			
		||||
                }));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const validateName = () => {
 | 
			
		||||
        if (contextName.length === 0) {
 | 
			
		||||
            setErrors(prev => ({ ...prev, name: 'Name can not be empty.' }));
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const clearErrors = () => {
 | 
			
		||||
@ -77,12 +80,9 @@ const useContextForm = (
 | 
			
		||||
        setLegalValues,
 | 
			
		||||
        setStickiness,
 | 
			
		||||
        getContextPayload,
 | 
			
		||||
        validateNameUniqueness,
 | 
			
		||||
        validateName,
 | 
			
		||||
        validateContext,
 | 
			
		||||
        setErrors,
 | 
			
		||||
        clearErrors,
 | 
			
		||||
        errors,
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default useContextForm;
 | 
			
		||||
 | 
			
		||||
@ -28,8 +28,8 @@ import EditUser from '../admin/users/EditUser/EditUser';
 | 
			
		||||
import { CreateApiToken } from '../admin/api-token/CreateApiToken/CreateApiToken';
 | 
			
		||||
import CreateEnvironment from '../environments/CreateEnvironment/CreateEnvironment';
 | 
			
		||||
import EditEnvironment from '../environments/EditEnvironment/EditEnvironment';
 | 
			
		||||
import CreateContext from '../context/CreateContext/CreateContext';
 | 
			
		||||
import EditContext from '../context/EditContext/EditContext';
 | 
			
		||||
import { CreateContext } from '../context/CreateContext/CreateContext';
 | 
			
		||||
import { EditContext } from '../context/EditContext/EditContext';
 | 
			
		||||
import EditTagType from '../tags/EditTagType/EditTagType';
 | 
			
		||||
import CreateTagType from '../tags/CreateTagType/CreateTagType';
 | 
			
		||||
import EditProject from '../project/Project/EditProject/EditProject';
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user