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:
parent
46f705461e
commit
665842680e
4 changed files with 66 additions and 13 deletions
|
|
@ -148,6 +148,7 @@ interface BaseModalProps {
|
||||||
onChangeOpenModal?: (open?: boolean) => void;
|
onChangeOpenModal?: (open?: boolean) => void;
|
||||||
type?: "modal" | "dialog";
|
type?: "modal" | "dialog";
|
||||||
onSubmit?: () => void;
|
onSubmit?: () => void;
|
||||||
|
onEscapeKeyDown?: (e: KeyboardEvent) => void;
|
||||||
}
|
}
|
||||||
function BaseModal({
|
function BaseModal({
|
||||||
open,
|
open,
|
||||||
|
|
@ -157,6 +158,7 @@ function BaseModal({
|
||||||
onChangeOpenModal,
|
onChangeOpenModal,
|
||||||
type = "dialog",
|
type = "dialog",
|
||||||
onSubmit,
|
onSubmit,
|
||||||
|
onEscapeKeyDown,
|
||||||
}: BaseModalProps) {
|
}: BaseModalProps) {
|
||||||
const headerChild = React.Children.toArray(children).find(
|
const headerChild = React.Children.toArray(children).find(
|
||||||
(child) => (child as React.ReactElement).type === Header,
|
(child) => (child as React.ReactElement).type === Header,
|
||||||
|
|
@ -204,7 +206,10 @@ function BaseModal({
|
||||||
) : (
|
) : (
|
||||||
<Dialog open={open} onOpenChange={setOpen}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
{triggerChild}
|
{triggerChild}
|
||||||
<DialogContent className={contentClasses}>
|
<DialogContent
|
||||||
|
onEscapeKeyDown={onEscapeKeyDown}
|
||||||
|
className={contentClasses}
|
||||||
|
>
|
||||||
{onSubmit ? (
|
{onSubmit ? (
|
||||||
<Form.Root
|
<Form.Root
|
||||||
onSubmit={(event) => {
|
onSubmit={(event) => {
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,9 @@ import "ace-builds/src-noconflict/mode-python";
|
||||||
import "ace-builds/src-noconflict/theme-github";
|
import "ace-builds/src-noconflict/theme-github";
|
||||||
import "ace-builds/src-noconflict/theme-twilight";
|
import "ace-builds/src-noconflict/theme-twilight";
|
||||||
// import "ace-builds/webpack-resolver";
|
// import "ace-builds/webpack-resolver";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import AceEditor from "react-ace";
|
import AceEditor from "react-ace";
|
||||||
|
import ReactAce from "react-ace/lib/ace";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { Input } from "../../components/ui/input";
|
import { Input } from "../../components/ui/input";
|
||||||
|
|
@ -26,6 +27,7 @@ import { useDarkStore } from "../../stores/darkStore";
|
||||||
import { CodeErrorDataTypeAPI } from "../../types/api";
|
import { CodeErrorDataTypeAPI } from "../../types/api";
|
||||||
import { codeAreaModalPropsType } from "../../types/components";
|
import { codeAreaModalPropsType } from "../../types/components";
|
||||||
import BaseModal from "../baseModal";
|
import BaseModal from "../baseModal";
|
||||||
|
import ConfirmationModal from "../confirmationModal";
|
||||||
|
|
||||||
export default function CodeAreaModal({
|
export default function CodeAreaModal({
|
||||||
value,
|
value,
|
||||||
|
|
@ -47,6 +49,8 @@ export default function CodeAreaModal({
|
||||||
const [height, setHeight] = useState<string | null>(null);
|
const [height, setHeight] = useState<string | null>(null);
|
||||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
|
const [openConfirmation, setOpenConfirmation] = useState(false);
|
||||||
|
const codeRef = useRef<ReactAce | null>(null);
|
||||||
const [error, setError] = useState<{
|
const [error, setError] = useState<{
|
||||||
detail: CodeErrorDataTypeAPI;
|
detail: CodeErrorDataTypeAPI;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
|
@ -123,10 +127,6 @@ export default function CodeAreaModal({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClick() {
|
|
||||||
processCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Function to be executed after the state changes
|
// Function to be executed after the state changes
|
||||||
const delayedFunction = setTimeout(() => {
|
const delayedFunction = setTimeout(() => {
|
||||||
|
|
@ -143,12 +143,36 @@ export default function CodeAreaModal({
|
||||||
};
|
};
|
||||||
}, [error, setHeight]);
|
}, [error, setHeight]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!openConfirmation) {
|
||||||
|
codeRef.current?.editor.focus();
|
||||||
|
}
|
||||||
|
}, [openConfirmation]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCode(value);
|
setCode(value);
|
||||||
}, [value, open]);
|
}, [value, open]);
|
||||||
|
|
||||||
return (
|
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.Trigger>{children}</BaseModal.Trigger>
|
||||||
<BaseModal.Header description={CODE_PROMPT_DIALOG_SUBTITLE}>
|
<BaseModal.Header description={CODE_PROMPT_DIALOG_SUBTITLE}>
|
||||||
<span className="pr-2"> {EDIT_CODE_TITLE} </span>
|
<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="flex h-full w-full flex-col transition-all">
|
||||||
<div className="h-full w-full">
|
<div className="h-full w-full">
|
||||||
<AceEditor
|
<AceEditor
|
||||||
|
ref={codeRef}
|
||||||
readOnly={readonly}
|
readOnly={readonly}
|
||||||
value={code}
|
value={code}
|
||||||
mode="python"
|
mode="python"
|
||||||
|
|
@ -209,7 +234,7 @@ export default function CodeAreaModal({
|
||||||
<div className="flex h-fit w-full justify-end">
|
<div className="flex h-fit w-full justify-end">
|
||||||
<Button
|
<Button
|
||||||
className="mt-3"
|
className="mt-3"
|
||||||
onClick={handleClick}
|
onClick={processCode}
|
||||||
type="submit"
|
type="submit"
|
||||||
id="checkAndSaveBtn"
|
id="checkAndSaveBtn"
|
||||||
disabled={readonly}
|
disabled={readonly}
|
||||||
|
|
@ -218,6 +243,28 @@ export default function CodeAreaModal({
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</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.Content>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import GenericIconComponent from "@/components/genericIconComponent";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import ShadTooltip from "../../components/shadTooltipComponent";
|
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
|
|
@ -38,12 +39,11 @@ function ConfirmationModal({
|
||||||
data,
|
data,
|
||||||
index,
|
index,
|
||||||
onConfirm,
|
onConfirm,
|
||||||
size,
|
|
||||||
open,
|
open,
|
||||||
onClose,
|
onClose,
|
||||||
onCancel,
|
onCancel,
|
||||||
|
...props
|
||||||
}: ConfirmationModalType) {
|
}: ConfirmationModalType) {
|
||||||
const Icon: any = nodeIconsLucide[icon];
|
|
||||||
const [modalOpen, setModalOpen] = useState(open ?? false);
|
const [modalOpen, setModalOpen] = useState(open ?? false);
|
||||||
const [flag, setFlag] = useState(false);
|
const [flag, setFlag] = useState(false);
|
||||||
|
|
||||||
|
|
@ -67,12 +67,12 @@ function ConfirmationModal({
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseModal size={size} open={modalOpen} setOpen={setModalOpen}>
|
<BaseModal {...props} open={open} setOpen={setModalOpen}>
|
||||||
<BaseModal.Trigger>{triggerChild}</BaseModal.Trigger>
|
<BaseModal.Trigger>{triggerChild}</BaseModal.Trigger>
|
||||||
<BaseModal.Header description={titleHeader ?? null}>
|
<BaseModal.Header description={titleHeader ?? null}>
|
||||||
<span className="pr-2">{title}</span>
|
<span className="pr-2">{title}</span>
|
||||||
<Icon
|
<GenericIconComponent
|
||||||
name="icon"
|
name={icon}
|
||||||
className="h-6 w-6 pl-1 text-foreground"
|
className="h-6 w-6 pl-1 text-foreground"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -457,6 +457,7 @@ export type ConfirmationModalType = {
|
||||||
| "large-h-full"
|
| "large-h-full"
|
||||||
| "small-h-full"
|
| "small-h-full"
|
||||||
| "medium-h-full";
|
| "medium-h-full";
|
||||||
|
onEscapeKeyDown?: (e: KeyboardEvent) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserManagementType = {
|
export type UserManagementType = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue