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:
commit
a471c671d7
6 changed files with 35 additions and 21 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue