/* * 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 { RemoveOutlined } from "@mui/icons-material"; import { Box, CircularProgress, IconButton, InputAdornment, Typography, useTheme, } from "@mui/material"; import Autocomplete from "@mui/material/Autocomplete"; import { forwardRef, SyntheticEvent, useState } from "react"; import { Input } from "@/app-components/inputs/Input"; import { useFind } from "@/hooks/crud/useFind"; import { useGetFromCache } from "@/hooks/crud/useGet"; import { useSearch } from "@/hooks/useSearch"; import { useTranslate } from "@/hooks/useTranslate"; import { EntityType, Format } from "@/services/types"; import { NlpPattern } from "@/types/block.types"; import { INlpEntity } from "@/types/nlp-entity.types"; type NlpPatternSelectProps = {}; const NlpPatternSelect = ({}: NlpPatternSelectProps, ref) => { const [selected, setSelected] = useState([]); const theme = useTheme(); const { t } = useTranslate(); const { onSearch, searchPayload } = useSearch({ $iLike: ["name"], }); const { data: options, isLoading } = useFind( { entity: EntityType.NLP_ENTITY, format: Format.FULL }, { hasCount: false, params: searchPayload }, ); const getNlpValueFromCache = useGetFromCache(EntityType.NLP_VALUE); function handleNlpEntityChange( _event: SyntheticEvent, entities: INlpEntity[], ): void { const intersection = selected.filter(({ entity: entityName }) => entities.find(({ name }) => name === entityName), ); const additions = entities.filter( ({ name }) => !selected.find(({ entity: entityName }) => name === entityName), ); const newSelection: NlpPattern[] = [ ...intersection, ...additions.map( ({ name }) => ({ entity: name, match: "entity", value: name, } as NlpPattern), ), ]; setSelected(newSelection); } const handleNlpValueChange = (entity: INlpEntity, valueId: string) => { const value = getNlpValueFromCache(valueId); if (!value) { throw new Error("Unable to find nlp value in cache"); } const newSelection = [...selected]; const update = newSelection.find(({ entity: e }) => e === entity.name); if (!update) { throw new Error("Unable to find nlp entity"); } if (value.id === entity.id) { update.match = "entity"; update.value = entity.name; } else { update.match = "value"; update.value = value.value; } }; return ( selected.find(({ entity: entityName }) => entityName === name), )} multiple={true} options={options} onChange={handleNlpEntityChange} renderOption={(props, { name, doc }, { selected }) => ( {name} {doc && ( {doc} )} )} getOptionLabel={({ name }) => name} isOptionEqualToValue={(option, value) => option.id === value.id} freeSolo={false} loading={isLoading} renderTags={(entities, getTagProps) => ( {entities.map((entity, index) => { const { key, onDelete } = getTagProps({ index }); const handleChange = ( event: SyntheticEvent, valueId: string, ) => { handleNlpValueChange(entity, valueId); }; return ( option ? getNlpValueFromCache(option)?.value || "-" : t("label.any") } disableClearable popupIcon={false} onChange={handleChange} sx={{ minWidth: 50, padding: 0, ".MuiAutocomplete-input": { minWidth: "100px !important", }, "& .MuiOutlinedInput-root": { paddingRight: "2rem !important", "&.MuiInputBase-sizeSmall": { padding: "0 !important", }, }, }} renderInput={(props) => ( onSearch(e.target.value)} InputProps={{ ...props.InputProps, startAdornment: ( {entity.name} ), endAdornment: ( {isLoading ? ( ) : ( )} ), }} /> )} /> ); })} )} renderInput={(props) => ( onSearch(e.target.value)} InputProps={{ ...props.InputProps, endAdornment: isLoading ? ( ) : null, }} /> )} /> ); }; NlpPatternSelect.displayName = "NlpPatternSelect"; export default forwardRef(NlpPatternSelect) as ( props: NlpPatternSelectProps & { ref?: React.ForwardedRef; }, ) => ReturnType;