enhancement: prevent esc on codeAreaModal (#3232)

* add onEscapeKeyDown

* refactor: Add ConfirmationModal to CodeAreaModal for better user experience

* refactor: Update CodeAreaModal to use ReactAce for code editing

* fix closing o x modal

* refactor: Update CodeAreaModal to use ReactAce for code editing

* [autofix.ci] apply automated fixes

* decompose object

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
This commit is contained in:
anovazzi1 2024-08-13 09:35:02 -03:00 committed by GitHub
commit 665842680e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 66 additions and 13 deletions

View file

@ -148,6 +148,7 @@ interface BaseModalProps {
onChangeOpenModal?: (open?: boolean) => void;
type?: "modal" | "dialog";
onSubmit?: () => void;
onEscapeKeyDown?: (e: KeyboardEvent) => void;
}
function BaseModal({
open,
@ -157,6 +158,7 @@ function BaseModal({
onChangeOpenModal,
type = "dialog",
onSubmit,
onEscapeKeyDown,
}: BaseModalProps) {
const headerChild = React.Children.toArray(children).find(
(child) => (child as React.ReactElement).type === Header,
@ -204,7 +206,10 @@ function BaseModal({
) : (
<Dialog open={open} onOpenChange={setOpen}>
{triggerChild}
<DialogContent className={contentClasses}>
<DialogContent
onEscapeKeyDown={onEscapeKeyDown}
className={contentClasses}
>
{onSubmit ? (
<Form.Root
onSubmit={(event) => {

View file

@ -4,8 +4,9 @@ import "ace-builds/src-noconflict/mode-python";
import "ace-builds/src-noconflict/theme-github";
import "ace-builds/src-noconflict/theme-twilight";
// import "ace-builds/webpack-resolver";
import { useEffect, useState } from "react";
import { useEffect, useRef, useState } from "react";
import AceEditor from "react-ace";
import ReactAce from "react-ace/lib/ace";
import IconComponent from "../../components/genericIconComponent";
import { Button } from "../../components/ui/button";
import { Input } from "../../components/ui/input";
@ -26,6 +27,7 @@ import { useDarkStore } from "../../stores/darkStore";
import { CodeErrorDataTypeAPI } from "../../types/api";
import { codeAreaModalPropsType } from "../../types/components";
import BaseModal from "../baseModal";
import ConfirmationModal from "../confirmationModal";
export default function CodeAreaModal({
value,
@ -47,6 +49,8 @@ export default function CodeAreaModal({
const [height, setHeight] = useState<string | null>(null);
const setSuccessData = useAlertStore((state) => state.setSuccessData);
const setErrorData = useAlertStore((state) => state.setErrorData);
const [openConfirmation, setOpenConfirmation] = useState(false);
const codeRef = useRef<ReactAce | null>(null);
const [error, setError] = useState<{
detail: CodeErrorDataTypeAPI;
} | null>(null);
@ -123,10 +127,6 @@ export default function CodeAreaModal({
}
}
function handleClick() {
processCode();
}
useEffect(() => {
// Function to be executed after the state changes
const delayedFunction = setTimeout(() => {
@ -143,12 +143,36 @@ export default function CodeAreaModal({
};
}, [error, setHeight]);
useEffect(() => {
if (!openConfirmation) {
codeRef.current?.editor.focus();
}
}, [openConfirmation]);
useEffect(() => {
setCode(value);
}, [value, open]);
return (
<BaseModal open={open} setOpen={setOpen}>
<BaseModal
onEscapeKeyDown={(e) => {
e.preventDefault();
if (code === value) {
setOpen(false);
} else {
if (
!(
codeRef.current?.editor.completer.popup &&
codeRef.current?.editor.completer.popup.isOpen
)
) {
setOpenConfirmation(true);
}
}
}}
open={open}
setOpen={setOpen}
>
<BaseModal.Trigger>{children}</BaseModal.Trigger>
<BaseModal.Header description={CODE_PROMPT_DIALOG_SUBTITLE}>
<span className="pr-2"> {EDIT_CODE_TITLE} </span>
@ -168,6 +192,7 @@ export default function CodeAreaModal({
<div className="flex h-full w-full flex-col transition-all">
<div className="h-full w-full">
<AceEditor
ref={codeRef}
readOnly={readonly}
value={code}
mode="python"
@ -209,7 +234,7 @@ export default function CodeAreaModal({
<div className="flex h-fit w-full justify-end">
<Button
className="mt-3"
onClick={handleClick}
onClick={processCode}
type="submit"
id="checkAndSaveBtn"
disabled={readonly}
@ -218,6 +243,28 @@ export default function CodeAreaModal({
</Button>
</div>
</div>
<ConfirmationModal
onClose={setOpenConfirmation}
onEscapeKeyDown={(e) => {
e.stopPropagation();
setOpenConfirmation(false);
}}
size="x-small"
icon="AlertTriangle"
confirmationText="Check & Save"
cancelText="Discard Changes"
open={openConfirmation}
onCancel={() => setOpen(false)}
onConfirm={() => {
processCode();
setOpenConfirmation(false);
}}
title="Caution"
>
<ConfirmationModal.Content>
<p>Are you sure you want to exit without saving your changes?</p>
</ConfirmationModal.Content>
</ConfirmationModal>
</BaseModal.Content>
</BaseModal>
);

View file

@ -1,3 +1,4 @@
import GenericIconComponent from "@/components/genericIconComponent";
import React, { useEffect, useState } from "react";
import ShadTooltip from "../../components/shadTooltipComponent";
import { Button } from "../../components/ui/button";
@ -38,12 +39,11 @@ function ConfirmationModal({
data,
index,
onConfirm,
size,
open,
onClose,
onCancel,
...props
}: ConfirmationModalType) {
const Icon: any = nodeIconsLucide[icon];
const [modalOpen, setModalOpen] = useState(open ?? false);
const [flag, setFlag] = useState(false);
@ -67,12 +67,12 @@ function ConfirmationModal({
);
return (
<BaseModal size={size} open={modalOpen} setOpen={setModalOpen}>
<BaseModal {...props} open={open} setOpen={setModalOpen}>
<BaseModal.Trigger>{triggerChild}</BaseModal.Trigger>
<BaseModal.Header description={titleHeader ?? null}>
<span className="pr-2">{title}</span>
<Icon
name="icon"
<GenericIconComponent
name={icon}
className="h-6 w-6 pl-1 text-foreground"
aria-hidden="true"
/>

View file

@ -457,6 +457,7 @@ export type ConfirmationModalType = {
| "large-h-full"
| "small-h-full"
| "medium-h-full";
onEscapeKeyDown?: (e: KeyboardEvent) => void;
};
export type UserManagementType = {