Fix flow settings validation and save button (#2360)

This pull request fixes the validation and save button behavior in the
flow settings modal. Previously, the save button was not disabled when
it should have been, and the endpoint name validation was not working
correctly. This PR updates the validation logic and ensures that the
save button is disabled when necessary.
This commit is contained in:
anovazzi1 2024-06-26 18:45:03 +00:00 committed by GitHub
commit a471c671d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 35 additions and 21 deletions

View file

@ -1,5 +1,5 @@
from datetime import datetime, timezone
import re
from datetime import datetime, timezone
from typing import List
from uuid import UUID
@ -211,8 +211,7 @@ def update_flow(
if settings_service.settings.remove_api_keys:
flow_data = remove_api_keys(flow_data)
for key, value in flow_data.items():
if value is not None:
setattr(db_flow, key, value)
setattr(db_flow, key, value)
webhook_component = get_webhook_component_in_flow(db_flow.data)
db_flow.webhook = webhook_component is not None
db_flow.updated_at = datetime.now(timezone.utc)

View file

@ -4,7 +4,7 @@ import { Label } from "../../components/ui/label";
import { Textarea } from "../../components/ui/textarea";
import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { InputProps } from "../../types/components";
import { cn } from "../../utils/utils";
import { cn, isEndpointNameValid } from "../../utils/utils";
export const EditFlowSettings: React.FC<InputProps> = ({
name,
@ -17,7 +17,7 @@ export const EditFlowSettings: React.FC<InputProps> = ({
setEndpointName,
}: InputProps): JSX.Element => {
const [isMaxLength, setIsMaxLength] = useState(false);
const [isEndpointNameValid, setIsEndpointNameValid] = useState(true);
const [validEndpointName, setValidEndpointName] = useState(true);
const [isInvalidName, setIsInvalidName] = useState(false);
const currentFlow = useFlowsManagerStore((state) => state.currentFlow);
@ -34,10 +34,6 @@ export const EditFlowSettings: React.FC<InputProps> = ({
invalid = true;
break;
}
if (value === currentFlow?.name) {
invalid = true;
break;
}
invalid = false;
}
setIsInvalidName(invalid);
@ -51,12 +47,8 @@ export const EditFlowSettings: React.FC<InputProps> = ({
const handleEndpointNameChange = (event: ChangeEvent<HTMLInputElement>) => {
// Validate the endpoint name
// use this regex r'^[a-zA-Z0-9_-]+$'
const isValid =
(/^[a-zA-Z0-9_-]+$/.test(event.target.value) &&
event.target.value.length <= maxLength) ||
// empty is also valid
event.target.value.length === 0;
setIsEndpointNameValid(isValid);
const isValid = isEndpointNameValid(event.target.value, maxLength);
setValidEndpointName(isValid);
setEndpointName!(event.target.value);
};
@ -129,7 +121,7 @@ export const EditFlowSettings: React.FC<InputProps> = ({
<Label>
<div className="edit-flow-arrangement mt-3">
<span className="font-medium">Endpoint Name</span>
{!isEndpointNameValid && (
{!validEndpointName && (
<span className="edit-flow-span">
Invalid endpoint name. Use only letters, numbers, hyphens, and
underscores ({maxLength} characters max).

View file

@ -6,6 +6,7 @@ import useAlertStore from "../../stores/alertStore";
import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { FlowSettingsPropsType } from "../../types/components";
import { FlowType } from "../../types/flow";
import { isEndpointNameValid } from "../../utils/utils";
import BaseModal from "../baseModal";
export default function FlowSettingsModal({
@ -22,13 +23,15 @@ export default function FlowSettingsModal({
const [name, setName] = useState(currentFlow!.name);
const [description, setDescription] = useState(currentFlow!.description);
const [endpoint_name, setEndpointName] = useState(currentFlow!.endpoint_name);
const [endpoint_name, setEndpointName] = useState(currentFlow!.endpoint_name??"");
const [isSaving, setIsSaving] = useState(false);
const [disableSave, setDisableSave] = useState(true);
function handleClick(): void {
setIsSaving(true);
currentFlow!.name = name;
currentFlow!.description = description;
currentFlow!.endpoint_name = endpoint_name;
currentFlow!.endpoint_name =
endpoint_name && endpoint_name.length > 0 ? endpoint_name : null;
saveFlow(currentFlow!)
?.then(() => {
setOpen(false);
@ -54,6 +57,18 @@ export default function FlowSettingsModal({
setNameList(tempNameList.filter((name) => name !== currentFlow!.name));
}, [flows]);
useEffect(() => {
if (
(!nameLists.includes(name) && currentFlow?.name !== name) ||
currentFlow?.description !== description ||
((currentFlow?.endpoint_name??"") !== endpoint_name &&
isEndpointNameValid(endpoint_name ?? "", 50))
) {
setDisableSave(false);
} else {
setDisableSave(true);
}
}, [nameLists, currentFlow, description, endpoint_name, name]);
return (
<BaseModal
open={open}
@ -80,8 +95,8 @@ export default function FlowSettingsModal({
<BaseModal.Footer
submit={{
label: "Save",
disabled: nameLists.includes(name) || name === currentFlow!.name,
dataTestId: "save-flow-settings",
disabled: disableSave,
loading: isSaving,
}}
/>

View file

@ -303,7 +303,7 @@ export type IconComponentProps = {
export type InputProps = {
name: string | null;
description: string | null;
endpointName?: string;
endpointName?: string|null;
maxLength?: number;
setName?: (name: string) => void;
setDescription?: (description: string) => void;

View file

@ -7,7 +7,7 @@ export type FlowType = {
id: string;
data: ReactFlowJsonObject | null;
description: string;
endpoint_name?: string;
endpoint_name?: string|null;
style?: FlowStyleType;
is_component?: boolean;
last_tested_version?: string;

View file

@ -463,3 +463,11 @@ export const logTypeIsError = (
return isErrorLog(outputs);
}
};
export function isEndpointNameValid(name: string, maxLength: number): boolean {
return (
(/^[a-zA-Z0-9_-]+$/.test(name) && name.length <= maxLength) ||
// empty is also valid
name.length === 0
);
}