Skip to content

Commit

Permalink
Max consecutive auto reply values are not properly displayed in the UI (
Browse files Browse the repository at this point in the history
#216)

* Don't delete a property if it's used buy someother property

* Don't show auto reply button while showing retry chat button

* WIP: Show numeric stepper input for max consecutive auto reply

* Show numeric stepper input for max consecutive auto reply

* Show numeric stepper input for max consecutive auto reply

* Update error message
  • Loading branch information
harishmohanraj authored May 22, 2024
1 parent 77713fd commit 6573b47
Show file tree
Hide file tree
Showing 8 changed files with 488 additions and 23 deletions.
2 changes: 1 addition & 1 deletion app/src/client/app/BuildPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const BuildPage = ({ user }: BuildPageProps) => {

const wrapperClass = document.body.classList.contains('server-error')
? 'h-[calc(100vh-173px)]'
: 'h-[calc(100vh-88px)]';
: 'h-[calc(100vh-80px)]';

const history = useHistory();
useEffect(() => {
Expand Down
24 changes: 18 additions & 6 deletions app/src/client/components/DynamicFormBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
checkForDependency,
} from '../utils/buildPageUtils';
import { set } from 'zod';
import { NumericStepperWithClearButton } from './form/NumericStepperWithClearButton';

interface DynamicFormBuilderProps {
allUserProperties: any;
Expand Down Expand Up @@ -147,12 +148,23 @@ const DynamicFormBuilder: React.FC<DynamicFormBuilderProps> = ({
<div key={key} className='w-full mt-2'>
<label htmlFor={key}>{formElementsObject.title}</label>
{formElementsObject.enum ? (
<SelectInput
id={key}
value={inputValue}
options={formElementsObject.enum}
onChange={(value) => handleChange(key, value)}
/>
formElementsObject.type === 'numericStepperWithClearButton' ? (
<div>
<NumericStepperWithClearButton
id={key}
value={inputValue}
formElementObject={formElementsObject}
onChange={(value) => handleChange(key, value)}
/>
</div>
) : (
<SelectInput
id={key}
value={inputValue}
options={formElementsObject.enum}
onChange={(value) => handleChange(key, value)}
/>
)
) : key === 'system_message' ? (
<TextArea
id={key}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const UserPropertyHandler = ({ data }: SecretsProps) => {
if (propertyName !== '') {
const currentPropertyName = _.has(updateExistingModel, 'name') ? updateExistingModel.name : '';
setNotificationErrorMessage(
`Oops! You can't delete '${currentPropertyName}' because it's being used in '${propertyName}'.`
`Oops! You can't delete '${currentPropertyName}' because it's being used by '${propertyName}'.`
);
} else {
await deleteUserModels({ uuid: updateExistingModel.uuid, type_name: updateExistingModel.type_name });
Expand Down
59 changes: 59 additions & 0 deletions app/src/client/components/form/NumericStepperWithClearButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, { useState } from 'react';

interface formElementObjectValues {
default?: string;
description?: string;
enum?: string[];
title?: string;
type?: string;
}

interface NumericStepperWithClearButtonProps {
id: string;
formElementObject?: formElementObjectValues;
value: number; // Pass the current value as a prop
onChange: (value: number | null) => void; // Prop to handle value changes
}

export const NumericStepperWithClearButton: React.FC<NumericStepperWithClearButtonProps> = ({
id,
formElementObject,
value,
onChange,
}) => {
const [inputValue, setInputValue] = useState<number | null>(value);

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const targetValue = e.target.value;
const newValue = targetValue === '' ? null : parseInt(e.target.value, 10);
setInputValue(newValue);
onChange(newValue); // Call parent onChange with new value
};

const handleClear = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
setInputValue(null); // Clear the local input
onChange(null); // Pass the empty string to parent onChange
};

return (
<div className='flex gap-4'>
<input
className='my-2 p-2 border rounded w-full'
type='number'
data-testid='numeric-stepper'
id={id}
placeholder={`${formElementObject?.description}. Enter a number or 'Clear' to use the default value 'None'.`}
value={inputValue ? inputValue : ''}
onChange={handleChange}
min='1'
/>
<button
onClick={handleClear}
className='rounded-md my-2 px-3.5 py-2.5 text-sm bg-airt-primary text-airt-font-base hover:bg-opacity-85 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600'
>
Clear
</button>
</div>
);
};
13 changes: 12 additions & 1 deletion app/src/client/hooks/useForm.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useState, useEffect } from 'react';
import _ from 'lodash';
import { JsonSchema, SelectedModelSchema } from '../interfaces/BuildPageInterfaces';

interface UseFormProps {
Expand Down Expand Up @@ -34,7 +35,17 @@ export const useForm = ({ jsonSchema, defaultValues }: UseFormProps) => {
if (property.enum && property.enum.length === 1) {
initialFormData[key] = property.enum[0]; // Auto-set single enum value
} else {
initialFormData[key] = property.default ?? ''; // Use default or empty string if no default
if (
_.has(property, 'anyOf') &&
_.isEqual(
_.map(property.anyOf, (o: any) => o.type),
['integer', 'null']
)
) {
initialFormData[key] = null;
} else {
initialFormData[key] = property.default ?? ''; // Use default or empty string if no default
}
}
}
});
Expand Down
45 changes: 45 additions & 0 deletions app/src/client/tests/NumericStepperWithClearButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { describe, test, expect, vi } from 'vitest';
import { render, fireEvent, screen } from '@testing-library/react';
import { NumericStepperWithClearButton } from '../components/form/NumericStepperWithClearButton';

const renderNumericStepper = (value: any, onChange: any, formElementObject = {}) => {
return render(
<NumericStepperWithClearButton
id='test-numeric-stepper'
value={value}
onChange={onChange}
formElementObject={formElementObject}
/>
);
};

describe('NumericStepperWithClearButton', () => {
test('renders and updates value on user interaction with complex formElementObject', () => {
const mockChangeHandler = vi.fn();
const formElementObject = {
default: '10',
description: 'Age',
enum: ['5', '10', '15'],
title: 'Select Age',
type: 'number',
};

const { getByPlaceholderText } = renderNumericStepper(5, mockChangeHandler, formElementObject);

// Check if component renders with correct placeholder based on description and default value
const placeholderText = "Age. Enter a number or 'Clear' to use the default value 'None'.";
expect(getByPlaceholderText(placeholderText)).toBeInTheDocument();

// Simulate user changing value
const input = screen.getByTestId('numeric-stepper');
fireEvent.change(input, { target: { value: '15' } });
expect(mockChangeHandler).toHaveBeenCalledWith(15);
expect(input).toHaveValue(15);

// Test clear functionality
const button = screen.getByRole('button', { name: 'Clear' });
fireEvent.click(button);
expect(mockChangeHandler).toHaveBeenCalledWith(null);
expect(input).toHaveValue(null);
});
});
Loading

0 comments on commit 6573b47

Please sign in to comment.