feat: enhance fieldset

This commit is contained in:
Mohamed Marrouchi 2024-11-27 11:16:00 +01:00
parent eba7308e16
commit 1da3a3d9ba
6 changed files with 186 additions and 121 deletions

View File

@ -232,7 +232,7 @@
"capture_context_vars": "Capture context variables?",
"block_event_type": "Type of event",
"patterns": "Patterns",
"no_patterns": "- No patterns -",
"no_patterns": "- No triggers -",
"text_patterns": " Text Patterns",
"triggers": "Triggers",
"payloads": "Payloads",
@ -558,7 +558,7 @@
"media_library": "Media Library",
"manage_roles": "Manage Roles",
"connect_with_sso": "Connect with SSO",
"add_pattern": "Add pattern",
"add_pattern": "New Trigger",
"mark_as_default": "Mark as Default",
"toggle": "Toggle button"
},

View File

@ -559,7 +559,7 @@
"media_library": "Bibliothéque Media",
"manage_roles": "Gérer les rôles",
"connect_with_sso": "Se connecter avec SSO",
"add_pattern": "Ajouter un motif",
"add_pattern": "Ajouter un déclencheur",
"mark_as_default": "Par Défaut",
"toggle": "Bouton de bascule"
},

View File

@ -0,0 +1,96 @@
/*
* Copyright © 2024 Hexastack. All rights reserved.
*
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/
import { ArrowDropDown } from "@mui/icons-material";
import {
Box,
Button,
List,
ListItemButton,
ListItemIcon,
ListItemText,
Popover,
SxProps,
Theme,
} from "@mui/material";
import React, { useState } from "react";
export interface DropdownButtonAction {
icon: React.ReactNode;
name: string;
defaultValue: any;
}
interface AddPatternProps {
actions: DropdownButtonAction[];
onClick: (action: DropdownButtonAction) => void;
label?: string;
icon?: React.ReactNode;
sx?: SxProps<Theme> | undefined;
}
const DropdownButton: React.FC<AddPatternProps> = ({
actions,
onClick,
label = "Add",
icon,
sx,
}) => {
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
const handleOpen = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const handleAddFieldset = (action: DropdownButtonAction) => {
onClick(action);
handleClose();
};
const open = Boolean(anchorEl);
return (
<Box sx={sx}>
<Button
variant="contained"
onClick={handleOpen}
startIcon={icon}
endIcon={<ArrowDropDown />}
>
{label}
</Button>
<Popover
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
>
<List>
{actions.map((action, index) => (
<ListItemButton
key={index}
onClick={() => handleAddFieldset(action)}
>
<ListItemIcon>{action.icon}</ListItemIcon>
<ListItemText primary={action.name} />
</ListItemButton>
))}
</List>
</Popover>
</Box>
);
};
export default DropdownButton;

View File

@ -117,6 +117,7 @@ const NlpPatternSelect = (
<Autocomplete
ref={ref}
size="medium"
fullWidth={true}
disabled={options.length === 0}
value={defaultValue}
multiple={true}

View File

@ -6,7 +6,7 @@
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/
import { Grid, MenuItem, TextFieldProps } from "@mui/material";
import { Box, TextFieldProps } from "@mui/material";
import { FC, useEffect, useState } from "react";
import { RegisterOptions, useFormContext } from "react-hook-form";
@ -25,6 +25,7 @@ import {
import { PostbackInput } from "./PostbackInput";
const isRegex = (str: Pattern) => {
return typeof str === "string" && str.startsWith("/") && str.endsWith("/");
};
@ -65,16 +66,9 @@ const PatternInput: FC<PatternInputProps> = ({
register,
formState: { errors },
} = useFormContext<IBlockAttributes>();
// const getNlpEntityFromCache = useGetFromCache(EntityType.NLP_ENTITY);
const [pattern, setPattern] = useState<Pattern>(value);
const [patternType, setPatternType] = useState<PatternType>(getType(value));
const patternType = getType(value);
const isPostbackType = ["payload", "content", "menu"].includes(patternType);
const types = [
{ value: "text", label: t("label.match_sound") },
{ value: "regex", label: t("label.regex") },
{ value: "payload", label: t("label.postback") },
{ value: "nlp", label: t("label.nlp") },
];
const registerInput = (
errorMessage: string,
idx: number,
@ -100,52 +94,14 @@ const PatternInput: FC<PatternInputProps> = ({
}, [pattern]);
return (
<>
<Grid item xs={2}>
<Input
select
label={t("label.type")}
value={isPostbackType ? "payload" : patternType}
onChange={(e) => {
const selected = e.target.value as PatternType;
switch (selected) {
case "regex": {
setPattern("//");
break;
}
case "nlp": {
setPattern([]);
break;
}
case "menu":
case "content":
case "payload": {
setPattern(null);
break;
}
default: {
setPattern("");
}
}
setPatternType(selected);
}}
>
{types.map((item) => (
<MenuItem key={item.value} value={item.value}>
{item.label}
</MenuItem>
))}
</Input>
</Grid>
<Grid item xs={9}>
<Box display="flex" flexGrow={1}>
{patternType === "nlp" && (
<NlpPatternSelect
patterns={pattern as NlpPattern[]}
onChange={setPattern}
/>
)}
{isPostbackType ? (
<PostbackInput
onChange={(payload) => {
@ -186,8 +142,7 @@ const PatternInput: FC<PatternInputProps> = ({
onChange={(e) => onChange(e.target.value)}
/>
) : null}
</Grid>
</>
</Box>
);
};

View File

@ -6,12 +6,21 @@
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/
import AddIcon from "@mui/icons-material/Add";
import DeleteIcon from "@mui/icons-material/Delete";
import { Box, Button, Grid, IconButton, styled } from "@mui/material";
import { FC, Fragment, useEffect, useState } from "react";
import {
Abc,
Add,
Mouse,
PsychologyAlt,
RemoveCircleOutline,
Spellcheck,
} from "@mui/icons-material";
import { Box, IconButton, styled } from "@mui/material";
import { FC, useEffect, useState } from "react";
import { useFormContext } from "react-hook-form";
import DropdownButton, {
DropdownButtonAction,
} from "@/app-components/buttons/DropdownButton";
import { useTranslate } from "@/hooks/useTranslate";
import { Pattern } from "@/types/block.types";
import { SXStyleOptions } from "@/utils/SXStyleOptions";
@ -21,11 +30,6 @@ import { getInputControls } from "../../utils/inputControls";
import PatternInput from "./PatternInput";
type PatternsInputProps = {
value: Pattern[];
onChange: (patterns: Pattern[]) => void;
minInput: number;
};
const StyledNoPatternsDiv = styled("div")(
SXStyleOptions({
color: "grey.500",
@ -35,6 +39,19 @@ const StyledNoPatternsDiv = styled("div")(
width: "100%",
}),
);
const actions: DropdownButtonAction[] = [
{ icon: <Spellcheck />, name: "Exact Match", defaultValue: "" },
{ icon: <Abc />, name: "Pattern Match", defaultValue: "//" },
{ icon: <PsychologyAlt />, name: "Intent Match", defaultValue: [] },
{ icon: <Mouse />, name: "Interaction", defaultValue: {} },
];
type PatternsInputProps = {
value: Pattern[];
onChange: (patterns: Pattern[]) => void;
minInput: number;
};
const PatternsInput: FC<PatternsInputProps> = ({ value, onChange }) => {
const { t } = useTranslate();
const [patterns, setPatterns] = useState<ValueWithId<Pattern>[]>(
@ -44,8 +61,8 @@ const PatternsInput: FC<PatternsInputProps> = ({ value, onChange }) => {
register,
formState: { errors },
} = useFormContext<any>();
const addInput = () => {
setPatterns([...patterns, createValueWithId<Pattern>("")]);
const addInput = (defaultValue: Pattern) => {
setPatterns([...patterns, createValueWithId<Pattern>(defaultValue)]);
};
const removeInput = (index: number) => {
const updatedPatterns = [...patterns];
@ -64,18 +81,13 @@ const PatternsInput: FC<PatternsInputProps> = ({ value, onChange }) => {
}, [patterns]);
return (
<Box>
<Grid container spacing={2}>
<Box display="flex" flexDirection="column">
<Box display="flex" flexDirection="column">
{patterns.length == 0 ? (
<StyledNoPatternsDiv>{t("label.no_patterns")}</StyledNoPatternsDiv>
) : (
patterns.map(({ value, id }, idx) => (
<Fragment key={id}>
<Grid item xs={1}>
<IconButton onClick={() => removeInput(idx)}>
<DeleteIcon />
</IconButton>
</Grid>
<Box display="flex" mt={2} key={id}>
<PatternInput
idx={idx}
value={value}
@ -87,19 +99,20 @@ const PatternsInput: FC<PatternsInputProps> = ({ value, onChange }) => {
t("message.text_is_required"),
)}
/>
</Fragment>
<IconButton size="small" color="error" onClick={() => removeInput(idx)}>
<RemoveCircleOutline />
</IconButton>
</Box>
))
)}
</Grid>
<Button
variant="contained"
color="primary"
onClick={addInput}
startIcon={<AddIcon />}
sx={{ marginTop: 2, float: "right" }}
>
{t("button.add_pattern")}
</Button>
</Box>
<DropdownButton
sx={{ alignSelf: "end", marginTop: 2 }}
label={t("button.add_pattern")}
actions={actions}
onClick={(action) => addInput(action.defaultValue as Pattern)}
icon={<Add />}
/>
</Box>
);
};